Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  dpdimsave.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <dpcache.hxx>
#include <dpdimsave.hxx>
#include <dpgroup.hxx>
#include <dpobject.hxx>
#include <dputil.hxx>
#include <document.hxx>

#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>

#include <svl/numformat.hxx>
#include <osl/diagnose.h>
#include <rtl/math.hxx>
#include <algorithm>

#include <globstr.hrc>
#include <scresid.hxx>
#include <utility>

using namespace com::sun::star;

ScDPSaveGroupItem::ScDPSaveGroupItem( OUString aName ) :
    aGroupName(std::move(aName)) {}

ScDPSaveGroupItem::~ScDPSaveGroupItem() {}

void ScDPSaveGroupItem::AddElement( const OUString& rName )
{
    aElements.push_back(rName);
}

void ScDPSaveGroupItem::AddElementsFromGroup( const ScDPSaveGroupItem& rGroup )
{
    // add all elements of the other group (used for nested grouping)
    aElements.insert( aElements.end(), rGroup.aElements.begin(), rGroup.aElements.end() );
}

bool ScDPSaveGroupItem::RemoveElement( const OUString& rName )
{
    auto it = std::find(aElements.begin(), aElements.end(), rName); //TODO: ignore case
    if (it != aElements.end())
    {
        aElements.erase(it);
        return true;
    }
    return false;   // not found
}

bool ScDPSaveGroupItem::IsEmpty() const
{
    return aElements.empty();
}

size_t ScDPSaveGroupItem::GetElementCount() const
{
    return aElements.size();
}

const OUString* ScDPSaveGroupItem::GetElementByIndex(size_t nIndex) const
{
    return (nIndex < aElements.size()) ? &aElements[ nIndex ] : nullptr;
}

void ScDPSaveGroupItem::Rename( const OUString& rNewName )
{
    aGroupName = rNewName;
}

void ScDPSaveGroupItem::RemoveElementsFromGroups( ScDPSaveGroupDimension& rDimension ) const
{
    // remove this group's elements from their groups in rDimension
    // (rDimension must be a different dimension from the one which contains this)

    for ( const auto& rElement : aElements )
        rDimension.RemoveFromGroups( rElement );
}

void ScDPSaveGroupItem::ConvertElementsToItems(SvNumberFormatter* pFormatter) const
{
    maItems.reserve(aElements.size());
    for (const auto& rElement : aElements)
    {
        sal_uInt32 nFormat = 0;
        double fValue;
        ScDPItemData aData;
        if (pFormatter->IsNumberFormat(rElement, nFormat, fValue))
            aData.SetValue(fValue);
        else
            aData.SetString(rElement);

        maItems.push_back(aData);
    }
}

bool ScDPSaveGroupItem::HasInGroup(const ScDPItemData& rItem) const
{
    return std::find(maItems.begin(), maItems.end(), rItem) != maItems.end();
}

void ScDPSaveGroupItem::AddToData(ScDPGroupDimension& rDataDim) const
{
    ScDPGroupItem aGroup(aGroupName);
    for (const auto& rItem : maItems)
        aGroup.AddElement(rItem);

    rDataDim.AddItem(aGroup);
}

ScDPSaveGroupDimension::ScDPSaveGroupDimension( OUString aSource, OUString aName ) :
    aSourceDim(std::move( aSource )),
    aGroupDimName(std::move( aName )),
    nDatePart( 0 )
{
}

ScDPSaveGroupDimension::ScDPSaveGroupDimension( OUString aSource, OUString aName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
    aSourceDim(std::move( aSource )),
    aGroupDimName(std::move( aName )),
    aDateInfo( rDateInfo ),
    nDatePart( nPart )
{
}

void ScDPSaveGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
{
    aDateInfo = rInfo;
    nDatePart = nPart;
}

void ScDPSaveGroupDimension::AddGroupItem( const ScDPSaveGroupItem& rItem )
{
    aGroups.push_back( rItem );
}

OUString ScDPSaveGroupDimension::CreateGroupName(std::u16string_view rPrefix)
{
    // create a name for a new group, using "Group1", "Group2" etc. (translated prefix in rPrefix)

    //TODO: look in all dimensions, to avoid clashes with automatic groups (=name of base element)?
    //TODO: (only dimensions for the same base)

    sal_Int32 nAdd = 1;                                 // first try is "Group1"
    const sal_Int32 nMaxAdd = nAdd + aGroups.size();    // limit the loop
    while ( nAdd <= nMaxAdd )
    {
        OUString aGroupName = rPrefix + OUString::number( nAdd );

        // look for existing groups
        bool bExists = std::any_of(aGroups.begin(), aGroups.end(),
            [&aGroupName](const ScDPSaveGroupItem& rGroup) {
                return rGroup.GetGroupName() == aGroupName; //TODO: ignore case
            });

        if ( !bExists )
            return aGroupName;          // found a new name

        ++nAdd;                         // continue with higher number
    }

    OSL_FAIL("CreateGroupName: no valid name found");
    return OUString();
}

const ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroup( const OUString& rGroupName ) const
{
    return const_cast< ScDPSaveGroupDimension* >( this )->GetNamedGroupAcc( rGroupName );
}

ScDPSaveGroupItem* ScDPSaveGroupDimension::GetNamedGroupAcc( const OUString& rGroupName )
{
    auto aIter = std::find_if(aGroups.begin(), aGroups.end(),
        [&rGroupName](const ScDPSaveGroupItem& rGroup) {
            return rGroup.GetGroupName() == rGroupName; //TODO: ignore case
        });
    if (aIter != aGroups.end())
        return &*aIter;

    return nullptr;        // none found
}

tools::Long ScDPSaveGroupDimension::GetGroupCount() const
{
    return aGroups.size();
}

const ScDPSaveGroupItem& ScDPSaveGroupDimension::GetGroupByIndex( tools::Long nIndex ) const
{
    return aGroups[nIndex];
}


void ScDPSaveGroupDimension::RemoveFromGroups( const OUString& rItemName )
{
    //  if the item is in any group, remove it from the group,
    //  also remove the group if it is empty afterwards

    for ( ScDPSaveGroupItemVec::iterator aIter(aGroups.begin()); aIter != aGroups.end(); ++aIter )
        if ( aIter->RemoveElement( rItemName ) )
        {
            if ( aIter->IsEmpty() )         // removed last item from the group?
                aGroups.erase( aIter );     // then remove the group

            return;     // don't have to look further
        }
}

void ScDPSaveGroupDimension::RemoveGroup(const OUString& rGroupName)
{
    auto aIter = std::find_if(aGroups.begin(), aGroups.end(),
        [&rGroupName](const ScDPSaveGroupItem& rGroup) {
            return rGroup.GetGroupName() == rGroupName; //TODO: ignore case
        });
    if (aIter != aGroups.end())
        aGroups.erase( aIter );
}

bool ScDPSaveGroupDimension::IsEmpty() const
{
    return aGroups.empty();
}

bool ScDPSaveGroupDimension::HasOnlyHidden(const ScDPUniqueStringSet& rVisible)
{
    // check if there are only groups that don't appear in the list of visible names

    return std::none_of(aGroups.begin(), aGroups.end(),
        [&rVisible](const ScDPSaveGroupItem& rGroup) { return rVisible.count(rGroup.GetGroupName()) > 0; });
}

void ScDPSaveGroupDimension::Rename( const OUString& rNewName )
{
    aGroupDimName = rNewName;
}

bool ScDPSaveGroupDimension::IsInGroup(const ScDPItemData& rItem) const
{
    return std::any_of(aGroups.begin(), aGroups.end(),
        [&rItem](const ScDPSaveGroupItem& rGroup) { return rGroup.HasInGroup(rItem); });
}

namespace {

bool isInteger(double fValue)
{
    return rtl::math::approxEqual(fValue, rtl::math::approxFloor(fValue));
}

void fillDateGroupDimension(
    ScDPCache& rCache, ScDPNumGroupInfo& rDateInfo, tools::Long nSourceDim, tools::Long nGroupDim,
    sal_Int32 nDatePart, const SvNumberFormatter* pFormatter)
{
    // Auto min/max is only used for "Years" part, but the loop is always
    // needed.
    double fSourceMin = 0.0;
    double fSourceMax = 0.0;
    bool bFirst = true;

    const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nSourceDim);
    for (const ScDPItemData& rItem : rItems)
    {
        if (rItem.GetType() != ScDPItemData::Value)
            continue;

        double fVal = rItem.GetValue();
        if (bFirst)
        {
            fSourceMin = fSourceMax = fVal;
            bFirst = false;
        }
        else
        {
            if (fVal < fSourceMin)
                fSourceMin = fVal;
            if ( fVal > fSourceMax )
                fSourceMax = fVal;
        }
    }

    // For the start/end values, use the same date rounding as in
    // ScDPNumGroupDimension::GetNumEntries (but not for the list of
    // available years).
    if (rDateInfo.mbAutoStart)
        rDateInfo.mfStart = rtl::math::approxFloor(fSourceMin);
    if (rDateInfo.mbAutoEnd)
        rDateInfo.mfEnd = rtl::math::approxFloor(fSourceMax) + 1;

    //TODO: if not automatic, limit fSourceMin/fSourceMax for list of year values?

    tools::Long nStart = 0, nEnd = 0; // end is inclusive

    switch (nDatePart)
    {
        case sheet::DataPilotFieldGroupBy::YEARS:
            nStart = ScDPUtil::getDatePartValue(
                fSourceMin, nullptr, sheet::DataPilotFieldGroupBy::YEARS, pFormatter);
            nEnd = ScDPUtil::getDatePartValue(fSourceMax, nullptr, sheet::DataPilotFieldGroupBy::YEARS, pFormatter);
            break;
        case sheet::DataPilotFieldGroupBy::QUARTERS: nStart = 1; nEnd = 4;   break;
        case sheet::DataPilotFieldGroupBy::MONTHS:   nStart = 1; nEnd = 12;  break;
        case sheet::DataPilotFieldGroupBy::DAYS:     nStart = 1; nEnd = 366; break;
        case sheet::DataPilotFieldGroupBy::HOURS:    nStart = 0; nEnd = 23;  break;
        case sheet::DataPilotFieldGroupBy::MINUTES:  nStart = 0; nEnd = 59;  break;
        case sheet::DataPilotFieldGroupBy::SECONDS:  nStart = 0; nEnd = 59;  break;
        default:
            OSL_FAIL("invalid date part");
    }

    // Now, populate the group items in the cache.
    rCache.ResetGroupItems(nGroupDim, rDateInfo, nDatePart);

    for (tools::Long nValue = nStart; nValue <= nEnd; ++nValue)
        rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, nValue));

    // add first/last entry (min/max)
    rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateFirst));
    rCache.SetGroupItem(nGroupDim, ScDPItemData(nDatePart, ScDPItemData::DateLast));
}

}

void ScDPSaveGroupDimension::AddToData( ScDPGroupTableData& rData ) const
{
    tools::Long nSourceIndex = rData.GetDimensionIndex( aSourceDim );
    if ( nSourceIndex < 0 )
        return;

    ScDPGroupDimension aDim( nSourceIndex, aGroupDimName );
    if ( nDatePart )
    {
        // date grouping

        aDim.SetDateDimension();
    }
    else
    {
        // normal (manual) grouping

        for (const auto& rGroup : aGroups)
            rGroup.AddToData(aDim);
    }

    rData.AddGroupDimension( aDim );
}

void ScDPSaveGroupDimension::AddToCache(ScDPCache& rCache) const
{
    tools::Long nSourceDim = rCache.GetDimensionIndex(aSourceDim);
    if (nSourceDim < 0)
        return;

    tools::Long nDim = rCache.AppendGroupField();
    SvNumberFormatter* pFormatter = rCache.GetDoc().GetFormatTable();

    if (nDatePart)
    {
        fillDateGroupDimension(rCache, aDateInfo, nSourceDim, nDim, nDatePart, pFormatter);
        return;
    }

    rCache.ResetGroupItems(nDim, aDateInfo, 0);
    for (const ScDPSaveGroupItem& rGI : aGroups)
    {
        rGI.ConvertElementsToItems(pFormatter);
        rCache.SetGroupItem(nDim, ScDPItemData(rGI.GetGroupName()));
    }

    const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nSourceDim);
    for (const ScDPItemData& rItem : rItems)
    {
        if (!IsInGroup(rItem))
            // Not in any group.  Add as its own group.
            rCache.SetGroupItem(nDim, rItem);
    }
}

ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( OUString aName, const ScDPNumGroupInfo& rInfo ) :
    aDimensionName(std::move( aName )),
    aGroupInfo( rInfo ),
    nDatePart( 0 )
{
}

ScDPSaveNumGroupDimension::ScDPSaveNumGroupDimension( OUString aName, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nPart ) :
    aDimensionName(std::move( aName )),
    aDateInfo( rDateInfo ),
    nDatePart( nPart )
{
}

void ScDPSaveNumGroupDimension::AddToData( ScDPGroupTableData& rData ) const
{
    tools::Long nSource = rData.GetDimensionIndex( aDimensionName );
    if ( nSource >= 0 )
    {
        ScDPNumGroupDimension aDim( aGroupInfo );           // aGroupInfo: value grouping
        if ( nDatePart )
            aDim.SetDateDimension();

        rData.SetNumGroupDimension( nSource, aDim );
    }
}

void ScDPSaveNumGroupDimension::AddToCache(ScDPCache& rCache) const
{
    tools::Long nDim = rCache.GetDimensionIndex(aDimensionName);
    if (nDim < 0)
        return;

    if (aDateInfo.mbEnable)
    {
        // Date grouping
        SvNumberFormatter* pFormatter = rCache.GetDoc().GetFormatTable();
        fillDateGroupDimension(rCache, aDateInfo, nDim, nDim, nDatePart, pFormatter);
    }
    else if (aGroupInfo.mbEnable)
    {
        // Number-range grouping

        // Look through the source entries for non-integer numbers, minimum
        // and maximum.

        // non-integer GroupInfo values count, too
        aGroupInfo.mbIntegerOnly =
            (aGroupInfo.mbAutoStart || isInteger(aGroupInfo.mfStart)) &&
            (aGroupInfo.mbAutoEnd || isInteger(aGroupInfo.mfEnd)) &&
            isInteger(aGroupInfo.mfStep);

        double fSourceMin = 0.0;
        double fSourceMax = 0.0;
        bool bFirst = true;

        const ScDPCache::ScDPItemDataVec& rItems = rCache.GetDimMemberValues(nDim);
        for (const ScDPItemData& rItem : rItems)
        {
            if (rItem.GetType() != ScDPItemData::Value)
                continue;

            double fValue = rItem.GetValue();
            if (bFirst)
            {
                fSourceMin = fSourceMax = fValue;
                bFirst = false;
                continue;
            }

            if (fValue < fSourceMin)
                fSourceMin = fValue;
            if (fValue > fSourceMax)
                fSourceMax = fValue;

            if (aGroupInfo.mbIntegerOnly && !isInteger(fValue))
            {
                // If any non-integer numbers are involved, the group labels
                // are shown including their upper limit.
                aGroupInfo.mbIntegerOnly = false;
            }
        }

        if (aGroupInfo.mbDateValues)
        {
            // special handling for dates: always integer, round down limits
            aGroupInfo.mbIntegerOnly = true;
            fSourceMin = rtl::math::approxFloor(fSourceMin);
            fSourceMax = rtl::math::approxFloor(fSourceMax) + 1;
        }

        if (aGroupInfo.mbAutoStart)
            aGroupInfo.mfStart = fSourceMin;
        if (aGroupInfo.mbAutoEnd)
            aGroupInfo.mfEnd = fSourceMax;

        //TODO: limit number of entries?

        tools::Long nLoopCount = 0;
        double fLoop = aGroupInfo.mfStart;

        rCache.ResetGroupItems(nDim, aGroupInfo, 0);

        // Use "less than" instead of "less or equal" for the loop - don't
        // create a group that consists only of the end value. Instead, the
        // end value is then included in the last group (last group is bigger
        // than the others). The first group has to be created nonetheless.
        // GetNumGroupForValue has corresponding logic.

        bool bFirstGroup = true;
        while (bFirstGroup || (fLoop < aGroupInfo.mfEnd && !rtl::math::approxEqual(fLoop, aGroupInfo.mfEnd)))
        {
            ScDPItemData aItem;
            aItem.SetRangeStart(fLoop);
            rCache.SetGroupItem(nDim, aItem);
            ++nLoopCount;
            fLoop = aGroupInfo.mfStart + nLoopCount * aGroupInfo.mfStep;
            bFirstGroup = false;

            // ScDPItemData values are compared with approxEqual
        }

        ScDPItemData aItem;
        aItem.SetRangeFirst();
        rCache.SetGroupItem(nDim, aItem);

        aItem.SetRangeLast();
        rCache.SetGroupItem(nDim, aItem);
    }
}

void ScDPSaveNumGroupDimension::SetGroupInfo( const ScDPNumGroupInfo& rNew )
{
    aGroupInfo = rNew;
}

void ScDPSaveNumGroupDimension::SetDateInfo( const ScDPNumGroupInfo& rInfo, sal_Int32 nPart )
{
    aDateInfo = rInfo;
    nDatePart = nPart;
}

namespace {

struct ScDPSaveGroupDimNameFunc
{
    OUString       maDimName;
    explicit     ScDPSaveGroupDimNameFunc( OUString aDimName ) : maDimName(std::move( aDimName )) {}
    bool         operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetGroupDimName() == maDimName; }
};

struct ScDPSaveGroupSourceNameFunc
{
    OUString       maSrcDimName;
    explicit     ScDPSaveGroupSourceNameFunc( OUString aSrcDimName ) : maSrcDimName(std::move( aSrcDimName )) {}
    bool         operator()( const ScDPSaveGroupDimension& rGroupDim ) const { return rGroupDim.GetSourceDimName() == maSrcDimName; }
};

// namespace

ScDPDimensionSaveData::ScDPDimensionSaveData()
{
}

bool ScDPDimensionSaveData::operator==( const ScDPDimensionSaveData& ) const
{
    return false;
}

void ScDPDimensionSaveData::AddGroupDimension( const ScDPSaveGroupDimension& rGroupDim )
{
    OSL_ENSURE( ::std::none_of( maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDim.GetGroupDimName() ) ),
        "ScDPDimensionSaveData::AddGroupDimension - group dimension exists already" );
    // ReplaceGroupDimension() adds new or replaces existing
    ReplaceGroupDimension( rGroupDim );
}

void ScDPDimensionSaveData::ReplaceGroupDimension( const ScDPSaveGroupDimension& ;rGroupDim )
{
    ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
        maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDim.GetGroupDimName() ) );
    if( aIt == maGroupDims.end() )
        maGroupDims.push_back( rGroupDim );
    else
        *aIt = rGroupDim;
}

void ScDPDimensionSaveData::RemoveGroupDimension( const OUString& rGroupDimName )
{
    ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
        maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
    if( aIt != maGroupDims.end() )
        maGroupDims.erase( aIt );
}

void ScDPDimensionSaveData::AddNumGroupDimension( const ScDPSaveNumGroupDimension&&nbsp;rGroupDim )
{
    OSL_ENSURE( maNumGroupDims.count( rGroupDim.GetDimensionName() ) == 0,
        "ScDPDimensionSaveData::AddNumGroupDimension - numeric group dimension exists already" );
    // ReplaceNumGroupDimension() adds new or replaces existing
    ReplaceNumGroupDimension( rGroupDim );
}

void ScDPDimensionSaveData::ReplaceNumGroupDimension( const ScDPSaveNumGroupDimension& rGroupDim )
{
    ScDPSaveNumGroupDimMap::iterator aIt = maNumGroupDims.find( rGroupDim.GetDimensionName() );
    if( aIt == maNumGroupDims.end() )
        maNumGroupDims.emplace( rGroupDim.GetDimensionName(), rGroupDim );
    else
        aIt->second = rGroupDim;
}

void ScDPDimensionSaveData::RemoveNumGroupDimension( const OUString& rGroupDimName )
{
    maNumGroupDims.erase( rGroupDimName );
}

void ScDPDimensionSaveData::WriteToData( ScDPGroupTableData& rData ) const
{
    //  rData is assumed to be empty
    //  AddToData also handles date grouping

    forconst auto& rGroupDim : maGroupDims )
        rGroupDim.AddToData( rData );

    forconst auto& rEntry : maNumGroupDims )
        rEntry.second.AddToData( rData );
}

void ScDPDimensionSaveData::WriteToCache(ScDPCache& rCache) const
{
    for (const auto& rEntry : maGroupDims)
        rEntry.AddToCache(rCache);
    for (const auto& rEntry : maNumGroupDims)
        rEntry.second.AddToCache(rCache);
}

const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimForBase( const OUString& rBaseDimName ) const
{
    return const_cast< ScDPDimensionSaveData* >( this )->GetGroupDimAccForBase( rBaseDimName );
}

const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDim( const OUString& rGroupDimName ) const
{
    return const_cast< ScDPDimensionSaveData* >( this )->GetNamedGroupDimAcc( rGroupDimName );
}

const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetFirstNamedGroupDim( const OUString& rBaseDimName ) const
{
    return const_cast< ScDPDimensionSaveData* >( this )->GetFirstNamedGroupDimAcc( rBaseDimName );
}

const ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNextNamedGroupDim( const OUString& rGroupDimName ) const
{
    return const_cast< ScDPDimensionSaveData* >( this )->GetNextNamedGroupDimAcc( rGroupDimName );
}

const ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDim( const OUString& rGroupDimName ) const
{
    return const_cast< ScDPDimensionSaveData* >( this )->GetNumGroupDimAcc( rGroupDimName );
}

ScDPSaveGroupDimension* ScDPDimensionSaveData::GetGroupDimAccForBase( const OUString& rBaseDimName )
{
    ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDimAcc( rBaseDimName );
    return pGroupDim ? pGroupDim : GetNextNamedGroupDimAcc( rBaseDimName );
}

ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNamedGroupDimAcc( const OUString&&nbsp;rGroupDimName )
{
    ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
        maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
    return (aIt == maGroupDims.end()) ? nullptr : &*aIt;
}

ScDPSaveGroupDimension* ScDPDimensionSaveData::GetFirstNamedGroupDimAcc( const OUString& rBaseDimName )
{
    ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
        maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupSourceNameFunc( rBaseDimName ) );
    return (aIt == maGroupDims.end()) ? nullptr : &*aIt;
}

ScDPSaveGroupDimension* ScDPDimensionSaveData::GetNextNamedGroupDimAcc( const OUString& rGroupDimName )
{
    // find the group dimension with the passed name
    ScDPSaveGroupDimVec::iterator aIt = ::std::find_if(
        maGroupDims.begin(), maGroupDims.end(), ScDPSaveGroupDimNameFunc( rGroupDimName ) );
    // find next group dimension based on the same source dimension name
    if( aIt != maGroupDims.end() )
        aIt = ::std::find_if( aIt + 1, maGroupDims.end(), ScDPSaveGroupSourceNameFunc( aIt->GetSourceDimName() ) );
    return (aIt == maGroupDims.end()) ? nullptr : &*aIt;
}

ScDPSaveNumGroupDimension* ScDPDimensionSaveData::GetNumGroupDimAcc( const OUString&&nbsp;rGroupDimName )
{
    ScDPSaveNumGroupDimMap::iterator aIt = maNumGroupDims.find( rGroupDimName );
    return (aIt == maNumGroupDims.end()) ? nullptr : &aIt->second;
}

bool ScDPDimensionSaveData::HasGroupDimensions() const
{
    return !maGroupDims.empty() || !maNumGroupDims.empty();
}

sal_Int32 ScDPDimensionSaveData::CollectDateParts( const OUString& rBaseDimName ) const
{
    sal_Int32 nParts = 0;
    // start with part of numeric group
    ifconst ScDPSaveNumGroupDimension* pNumDim = GetNumGroupDim( rBaseDimName ) )
        nParts |= pNumDim->GetDatePart();
    // collect parts from all matching group dimensions
    forconst ScDPSaveGroupDimension* pGroupDim = GetFirstNamedGroupDim( rBaseDimName ); pGroupDim; pGroupDim = GetNextNamedGroupDim( pGroupDim->GetGroupDimName() ) )
        nParts |= pGroupDim->GetDatePart();

    return nParts;
}

OUString ScDPDimensionSaveData::CreateGroupDimName(
    const OUString& rSourceName, const ScDPObject& rObject, bool bAllowSource,
    const std::vector<OUString>* pDeletedNames )
{
    // create a name for the new dimension by appending a number to the original
    // dimension's name

    bool bUseSource = bAllowSource;     // if set, try the unchanged original name first

    sal_Int32 nAdd = 2;                 // first try is "Name2"
    const sal_Int32 nMaxAdd = 1000;     // limit the loop
    while ( nAdd <= nMaxAdd )
    {
        OUString aDimName( rSourceName );
        if ( !bUseSource )
            aDimName += OUString::number(nAdd);

        // look for existing group dimensions
        bool bExists = std::any_of(maGroupDims.begin(), maGroupDims.end(),
            [&aDimName](const ScDPSaveGroupDimension& rDim) {
                return rDim.GetGroupDimName() == aDimName; //TODO: ignore case
            });

        // look for base dimensions that happen to have that name
        if ( !bExists && rObject.IsDimNameInUse( aDimName ) )
        {
            if ( pDeletedNames &&
                 std::find( pDeletedNames->begin(), pDeletedNames->end(), aDimName ) != pDeletedNames->end() )
            {
                // allow the name anyway if the name is in pDeletedNames
            }
            else
                bExists = true;
        }

        if ( !bExists )
            return aDimName;            // found a new name

        if ( bUseSource )
            bUseSource = false;
        else
            ++nAdd;                     // continue with higher number
    }
    OSL_FAIL("CreateGroupDimName: no valid name found");
    return OUString();
}

namespace
{
    const TranslateId aDatePartIds[] =
    {
        STR_DPFIELD_GROUP_BY_SECONDS,
        STR_DPFIELD_GROUP_BY_MINUTES,
        STR_DPFIELD_GROUP_BY_HOURS,
        STR_DPFIELD_GROUP_BY_DAYS,
        STR_DPFIELD_GROUP_BY_MONTHS,
        STR_DPFIELD_GROUP_BY_QUARTERS,
        STR_DPFIELD_GROUP_BY_YEARS
    };
}

OUString ScDPDimensionSaveData::CreateDateGroupDimName(
    sal_Int32 nDatePart, const ScDPObject& rObject, bool bAllowSource,
    const std::vector<OUString>* pDeletedNames )
{
    using namespace css::sheet::DataPilotFieldGroupBy;
    OUString aPartName;
    switch( nDatePart )
    {
        case SECONDS:  aPartName = ScResId(aDatePartIds[0]); break;
        case MINUTES:  aPartName = ScResId(aDatePartIds[1]); break;
        case HOURS:    aPartName = ScResId(aDatePartIds[2]); break;
        case DAYS:     aPartName = ScResId(aDatePartIds[3]); break;
        case MONTHS:   aPartName = ScResId(aDatePartIds[4]); break;
        case QUARTERS: aPartName = ScResId(aDatePartIds[5]); break;
        case YEARS:    aPartName = ScResId(aDatePartIds[6]); break;
    }
    OSL_ENSURE(!aPartName.isEmpty(), "ScDPDimensionSaveData::CreateDateGroupDimName - invalid date part");
    return CreateGroupDimName( aPartName, rObject, bAllowSource, pDeletedNames );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=92 H=93 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge