23#include <document.hxx> 
   27#include <osl/diagnose.h> 
   28#include <rtl/math.hxx> 
   31#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> 
   33#include <unordered_map> 
   34#include <unordered_set> 
   40using ::com::sun::star::uno::Any;
 
   41using ::com::sun::star::uno::Sequence;
 
   44using ::std::shared_ptr;
 
   53    ScDPGroupNumFilter(std::vector<ScDPItemData>&& rValues, 
const ScDPNumGroupInfo& rInfo);
 
   64ScDPGroupNumFilter::ScDPGroupNumFilter( std::vector<ScDPItemData>&& rValues, 
const ScDPNumGroupInfo& rInfo) :
 
   67bool ScDPGroupNumFilter::match(
const ScDPItemData& rCellData)
 const 
   72    for (
const auto& rValue : maValues)
 
   74        double fVal = rValue.GetValue();
 
   77            if (std::signbit(fVal))
 
   80                if (rCellData.
GetValue() < maNumInfo.mfStart)
 
   85            if (maNumInfo.mfEnd < rCellData.
GetValue())
 
   92        double high = low + maNumInfo.mfStep;
 
   93        if (maNumInfo.mbIntegerOnly)
 
  103std::vector<ScDPItemData> ScDPGroupNumFilter::getMatchValues()
 const 
  105    return std::vector<ScDPItemData>();
 
  117    virtual std::vector<ScDPItemData> 
getMatchValues() 
const override;
 
  127ScDPGroupDateFilter::ScDPGroupDateFilter(
 
  130    maNullDate(rNullDate),
 
  135bool ScDPGroupDateFilter::match( 
const ScDPItemData & rCellData )
 const 
  138    using ::rtl::math::approxFloor;
 
  139    using ::rtl::math::approxEqual;
 
  149        sal_Int32 nGroupType = rValue.GetGroupValue().mnGroupType;
 
  150        sal_Int32 
nValue = rValue.GetGroupValue().mnValue;
 
  155        if (rCellData.
GetValue() < maNumInfo.mfStart && !approxEqual(rCellData.
GetValue(), maNumInfo.mfStart))
 
  162        if (rCellData.
GetValue() > maNumInfo.mfEnd && !approxEqual(rCellData.
GetValue(), maNumInfo.mfEnd))
 
  169        if (nGroupType == DataPilotFieldGroupBy::HOURS || nGroupType == DataPilotFieldGroupBy::MINUTES ||
 
  170            nGroupType == DataPilotFieldGroupBy::SECONDS)
 
  175            sal_uInt16 nHour, nMinute, nSecond;
 
  176            double fFractionOfSecond;
 
  181                case DataPilotFieldGroupBy::HOURS:
 
  187                case DataPilotFieldGroupBy::MINUTES:
 
  189                    if (nMinute == nValue)
 
  193                case DataPilotFieldGroupBy::SECONDS:
 
  195                    if (nSecond == nValue)
 
  200                    OSL_FAIL(
"invalid time part");
 
  206        Date date = maNullDate + 
static_cast<sal_Int32
>(approxFloor(rCellData.
GetValue()));
 
  209            case DataPilotFieldGroupBy::YEARS:
 
  211                sal_Int32 
year = 
static_cast<sal_Int32
>(date.
GetYear());
 
  216            case DataPilotFieldGroupBy::QUARTERS:
 
  218                sal_Int32 qtr =  1 + (
static_cast<sal_Int32
>(date.
GetMonth()) - 1) / 3;
 
  223            case DataPilotFieldGroupBy::MONTHS:
 
  230            case DataPilotFieldGroupBy::DAYS:
 
  233                sal_Int32 days = (date - yearStart) + 1;       
 
  244                OSL_FAIL(
"invalid date part");
 
  251std::vector<ScDPItemData> ScDPGroupDateFilter::getMatchValues()
 const 
  253    return std::vector<ScDPItemData>();
 
  272        return nGroupValue == nChildValue;
 
  277        case css::sheet::DataPilotFieldGroupBy::MONTHS:
 
  279            if (nGroupPart == css::sheet::DataPilotFieldGroupBy::QUARTERS)
 
  281                return (nGroupValue - 1 == (nChildValue - 1) / 3);
 
  283        case css::sheet::DataPilotFieldGroupBy::DAYS:
 
  285            if (nGroupPart == css::sheet::DataPilotFieldGroupBy::MONTHS ||
 
  286                nGroupPart == css::sheet::DataPilotFieldGroupBy::QUARTERS)
 
  289                aDate.AddDays(nChildValue - 1);            
 
  290                sal_Int32 nCompare = aDate.GetMonth();
 
  291                if (nGroupPart == css::sheet::DataPilotFieldGroupBy::QUARTERS)
 
  292                    nCompare = ( ( nCompare - 1 ) / 3 ) + 1;    
 
  294                return nGroupValue == nCompare;
 
  319        [&rData](
const ScDPItemData& rElement) { return rElement.IsCaseInsEqual(rData); });
 
  325        [&rOther](
const ScDPItemData& rElement) { return rOther.HasElement(rElement); });
 
  335    nSourceDim( nSource ),
 
  337    aGroupName(
std::move( aNewName )),
 
  338    mbDateDimension(false)
 
  348    nSourceDim( rOther.nSourceDim ),
 
  349    nGroupDim( rOther.nGroupDim ),
 
  350    aGroupName( rOther.aGroupName ),
 
  351    aItems( rOther.aItems ),
 
  352    mbDateDimension(rOther.mbDateDimension)
 
  368    aItems.push_back( rItem );
 
  389        [&rData](
const ScDPGroupItem& rItem) { return rItem.HasElement(rData); });
 
  390    if (aIter != 
aItems.end())
 
  399        [&rName](
const ScDPGroupItem& rItem) { return rItem.GetName().IsCaseInsEqual(rName); });
 
  400    if (aIter != 
aItems.end())
 
  427    aGroupInfo(rInfo), mbDateDimension(false) {}
 
  430    aGroupInfo(rOther.aGroupInfo), mbDateDimension(rOther.mbDateDimension) {}
 
  467    pSourceData( pSource ),
 
  470    OSL_ENSURE( pSource, 
"ScDPGroupTableData: pSource can't be NULL" );
 
  485    aGroups.push_back( aNewGroup );
 
  602        rGroup.DisposeData();
 
  612    pSourceData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
 
  627class FindCaseInsensitive
 
  635        return maValue.IsCaseInsEqual(rItem);
 
  644    typedef std::unordered_map<tools::Long, const ScDPGroupDimension*> GroupFieldMapType;
 
  645    GroupFieldMapType aGroupFieldIds;
 
  647    for (
const auto& rGroup : 
aGroups)
 
  649        aGroupFieldIds.emplace(rGroup.GetGroupDim(), &rGroup);
 
  652    vector<ScDPFilteredCache::Criterion> aNewCriteria;
 
  653    aNewCriteria.reserve(rCriteria.size() + 
aGroups.size());
 
  658    GroupFieldMapType::const_iterator itrGrpEnd = aGroupFieldIds.end();
 
  659    for (
const auto& rCriterion : rCriteria)
 
  661        std::vector<ScDPItemData> aMatchValues = rCriterion.mpFilter->getMatchValues();
 
  663        GroupFieldMapType::const_iterator itrGrp = aGroupFieldIds.find(rCriterion.mnFieldIndex);
 
  664        if (itrGrp == itrGrpEnd)
 
  682                        std::make_shared<ScDPGroupDateFilter>(
 
  689                        std::make_shared<ScDPGroupNumFilter>(std::move(aMatchValues), *pNumInfo);
 
  692                aNewCriteria.push_back(aCri);
 
  697                aNewCriteria.push_back(rCriterion);
 
  715                    std::make_shared<ScDPGroupDateFilter>(
 
  718                aNewCriteria.push_back(aCri);
 
  726                aCri.
mpFilter = std::make_shared<ScDPFilteredCache::GroupFilter>();
 
  731                for (
size_t i = 0; 
i < nGroupItemCount; ++
i)
 
  738                    if (std::none_of(aMatchValues.begin(), aMatchValues.end(), FindCaseInsensitive(pGrpItem->
GetName())))
 
  744                aNewCriteria.push_back(aCri);
 
  748    rCriteria.swap(aNewCriteria);
 
  754    pSourceData->FilterCacheTable(std::move(rCriteria), std::move(rCatDims));
 
  760    pSourceData->GetDrillDownData(std::move(rCriteria), std::move(rCatDims), rData);
 
  770    sal_Int32 nRowSize = rCacheTable.
getRowSize();
 
  771    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
 
  806    sal_Int32 nGroupedColumns = 
aGroups.size();
 
  812        bool bDateDim = 
false;
 
  814        sal_Int32 nSourceDim = nColumn;
 
  835            bDateDim = 
pNumGroups[nColumn].IsDateDimension();
 
  854        if (bDateDim && pNumInfo)
 
  863                    pData->GetValue(), pNumInfo, nDatePart, pFormatter);
 
  883        [&nGroupDim](
const ScDPGroupDimension& rDim) { return rDim.GetGroupDim() == nGroupDim; });
 
  885        return aIter->GetSourceDim();
 
  896        return pNumGroups[nDimension].GetInfo().mbEnable ||
 
  901        [&nDimension](
const ScDPGroupDimension& rDim) { return rDim.GetGroupDim() == nDimension; });
 
  903        return aIter->IsDateDimension();
 
  909                                    const ScDPItemData& rBaseData, sal_Int32 nBaseIndex )
 const 
  913            return rDim.GetGroupDim() == nGroupIndex && rDim.GetSourceDim() == nBaseIndex; });
 
  919            return isDateInGroup(rGroupData, rBaseData);
 
  932    OSL_FAIL(
"IsInGroup: no group dimension found");
 
  937                                         const ScDPItemData& rSecondData, sal_Int32 nSecondIndex )
 const 
  941    for ( 
const auto& rDim : 
aGroups )
 
  949    if ( pFirstDim && pSecondDim )
 
  953        if (bFirstDate || bSecondDate)
 
  956            if (!bFirstDate || !bSecondDate)
 
  958                OSL_FAIL( 
"mix of date and non-date groups" );
 
  962            return isDateInGroup(rFirstData, rSecondData);
 
  967        if ( pFirstItem && pSecondItem )
 
  972        else if ( pFirstItem )
 
  977        else if ( pSecondItem )
 
  989    OSL_FAIL(
"HasCommonElement: no group dimension found");
 
 1011    if (rItem1 == 
nullptr || rItem2 == 
nullptr)
 
 1020    cout << 
"--- ScDPGroupTableData" << 
endl;
 
 1023        cout << 
"* dimension: " << 
i << 
endl;
 
 1027    cout << 
"---" << 
endl;
 
sal_Int16 GetYear() const
 
sal_uInt16 GetMonth() const
 
This class represents the cached data part of the datapilot cache table implementation.
 
sal_Int32 GetGroupType(tools::Long nDim) const
Return a group type identifier.
 
const ScDPItemData * GetItemDataById(tools::Long nDim, SCROW nId) const
 
SCROW GetIdByItemData(tools::Long nDim, const ScDPItemData &rItem) const
 
void GetGroupDimMemberIds(tools::Long nDim, std::vector< SCROW > &rIds) const
 
const ScDPNumGroupInfo * GetNumGroupInfo(tools::Long nDim) const
 
interface class used for filtering of rows.
 
virtual std::vector< ScDPItemData > getMatchValues() const =0
 
virtual bool match(const ScDPItemData &rCellData) const =0
returns true if the matching condition is met for a single cell value, or false otherwise.
 
multi-item (group) filter.
 
void addMatchItem(const ScDPItemData &rItem)
 
This class is only a wrapper to the actual cache, to provide filtering on the raw data based on the q...
 
sal_Int32 getRowSize() const
 
bool isRowActive(sal_Int32 nRow, sal_Int32 *pLastRow=nullptr) const
Check whether a specified row is active or not.
 
const ScDPCache & getCache() const
 
tools::Long GetSourceDim() const
 
ScDPGroupDimension & operator=(const ScDPGroupDimension &rOther)
 
ScDPGroupDimension(tools::Long nSource, OUString aNewName)
 
const ScDPGroupItem * GetGroupByIndex(size_t nIndex) const
 
bool IsDateDimension() const
 
const ScDPGroupItem * GetGroupForData(const ScDPItemData &rData) const
 
tools::Long GetGroupDim() const
 
size_t GetItemCount() const
 
const ScDPGroupItem * GetGroupForName(const ScDPItemData &rName) const
 
std::vector< SCROW > maMemberEntries
 
std::vector< ScDPGroupItem > aItems
 
const std::vector< SCROW > & GetColumnEntries(const ScDPFilteredCache &rCacheTable) const
 
void SetGroupDim(tools::Long nDim)
 
void AddItem(const ScDPGroupItem &rItem)
 
ScDPItemDataVec aElements
 
void AddElement(const ScDPItemData &rName)
 
bool HasElement(const ScDPItemData &rData) const
 
void FillGroupFilter(ScDPFilteredCache::GroupFilter &rFilter) const
 
ScDPGroupItem(const ScDPItemData &rName)
 
const ScDPItemData & GetName() const
 
bool HasCommonElement(const ScDPGroupItem &rOther) const
 
virtual sal_Int32 GetSourceDim(sal_Int32 nDim) override
 
virtual const ScDPItemData * GetMemberById(sal_Int32 nDim, sal_Int32 nId) override
 
virtual sal_Int32 GetMembersCount(sal_Int32 nDim) override
 
virtual bool IsNumOrDateGroup(sal_Int32 nDim) const override
 
virtual bool HasCommonElement(const ScDPItemData &rFirstData, sal_Int32 nFirstIndex, const ScDPItemData &rSecondData, sal_Int32 nSecondIndex) const override
 
virtual void FilterCacheTable(std::vector< ScDPFilteredCache::Criterion > &&rCriteria, std::unordered_set< sal_Int32 > &&rDataDims) override
 
sal_Int32 GetDimensionIndex(std::u16string_view rName)
 
std::shared_ptr< ScDPTableData > pSourceData
 
virtual void CalcResults(CalcInfo &rInfo, bool bAutoShow) override
 
virtual void SetEmptyFlags(bool bIgnoreEmptyRows, bool bRepeatIfEmpty) override
 
virtual void DisposeData() override
 
virtual void CreateCacheTable() override
 
virtual bool IsDateDimension(sal_Int32 nDim) override
 
virtual sal_Int32 GetGroupBase(sal_Int32 nGroupDim) const override
 
virtual bool getIsDataLayoutDimension(sal_Int32 nColumn) override
 
void FillGroupValues(std::vector< SCROW > &rItems, const std::vector< sal_Int32 > &rDims)
 
virtual sal_uInt32 GetNumberFormat(sal_Int32 nDim) override
 
virtual bool IsRepeatIfEmpty() override
 
virtual bool IsBaseForGroup(sal_Int32 nDim) const override
 
void GetNumGroupInfo(tools::Long nDimension, ScDPNumGroupInfo &rInfo)
 
virtual void Dump() const override
 
bool IsNumGroupDimension(tools::Long nDimension) const
 
void SetNumGroupDimension(sal_Int32 nIndex, const ScDPNumGroupDimension &rGroup)
 
virtual const std::vector< SCROW > & GetColumnEntries(sal_Int32 nColumn) override
 
virtual const ScDPFilteredCache & GetCacheTable() const override
 
void AddGroupDimension(const ScDPGroupDimension &rGroup)
 
virtual ~ScDPGroupTableData() override
 
std::unique_ptr< ScDPNumGroupDimension[]> pNumGroups
 
virtual bool IsInGroup(const ScDPItemData &rGroupData, sal_Int32 nGroupIndex, const ScDPItemData &rBaseData, sal_Int32 nBaseIndex) const override
 
virtual void GetDrillDownData(std::vector< ScDPFilteredCache::Criterion > &&rCriteria, std::unordered_set< sal_Int32 > &&rCatDims, css::uno::Sequence< css::uno::Sequence< css::uno::Any > > &rData) override
 
void ModifyFilterCriteria(::std::vector< ScDPFilteredCache::Criterion > &rCriteria)
 
virtual void ReloadCacheTable() override
 
ScDPGroupTableData(const std::shared_ptr< ScDPTableData > &pSource, ScDocument *pDocument)
 
std::vector< ScDPGroupDimension > aGroups
 
virtual OUString getDimensionName(sal_Int32 nColumn) override
 
virtual sal_Int32 GetColumnCount() override
use (new) typed collection instead of ScStrCollection or separate Str and ValueCollection
 
virtual sal_Int32 Compare(sal_Int32 nDim, sal_Int32 nDataId1, sal_Int32 nDataId2) override
 
When assigning a string value, you can also assign an interned string whose life-cycle is managed by ...
 
void SetRangeStart(double fVal)
 
static const sal_Int32 DateFirst
 
static sal_Int32 Compare(const ScDPItemData &rA, const ScDPItemData &rB)
 
bool IsCaseInsEqual(const ScDPItemData &r) const
 
static const sal_Int32 DateLast
 
GroupValueAttr GetGroupValue() const
 
ScDPNumGroupDimension & operator=(const ScDPNumGroupDimension &rOther)
 
std::vector< SCROW > maMemberEntries
 
ScDPNumGroupInfo aGroupInfo
 
const std::vector< SCROW > & GetNumEntries(SCCOL nSourceDim, const ScDPCache *pCache) const
 
bool IsDateDimension() const
 
const ScDPNumGroupInfo & GetInfo() const
 
Base class that abstracts different data source types of a datapilot table.
 
static void ProcessRowData(CalcInfo &rInfo, const CalcRowData &rData, bool bAutoShow)
 
void FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPFilteredCache &rCacheTable, const CalcInfo &rInfo, CalcRowData &rData)
 
static sal_Int32 getDatePartValue(double fValue, const ScDPNumGroupInfo *pInfo, sal_Int32 nDatePart, const SvNumberFormatter *pFormatter)
 
static double getNumGroupStartValue(double fValue, const ScDPNumGroupInfo &rInfo)
 
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
 
const sal_uInt16 SC_DP_LEAPYEAR
 
std::unique_ptr< sal_Int32[]> pData
 
constexpr OUStringLiteral aData
 
PyObject_HEAD PyUNO_callable_Internals * members
 
TOOLS_DLLPUBLIC SvStream & endl(SvStream &rStr)
 
single filtering criterion.
 
std::shared_ptr< FilterBase > mpFilter
 
This structure stores dimension information used when calculating results.
 
::std::vector< sal_Int32 > aPageDims
 
::std::vector< sal_Int32 > aRowLevelDims
 
::std::vector< sal_Int32 > aColLevelDims
 
This structure stores vector arrays that hold intermediate data for each row during cache table itera...