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>
39 using ::com::sun::star::uno::Any;
40 using ::com::sun::star::uno::Sequence;
43 using ::std::shared_ptr;
52 ScDPGroupNumFilter(std::vector<ScDPItemData>&& rValues,
const ScDPNumGroupInfo& rInfo);
63 ScDPGroupNumFilter::ScDPGroupNumFilter( std::vector<ScDPItemData>&& rValues,
const ScDPNumGroupInfo& rInfo) :
66 bool ScDPGroupNumFilter::match(
const ScDPItemData& rCellData)
const
71 for (
const auto& rValue : maValues)
73 double fVal = rValue.GetValue();
76 if (std::signbit(fVal))
79 if (rCellData.
GetValue() < maNumInfo.mfStart)
84 if (maNumInfo.mfEnd < rCellData.
GetValue())
91 double high = low + maNumInfo.mfStep;
92 if (maNumInfo.mbIntegerOnly)
102 std::vector<ScDPItemData> ScDPGroupNumFilter::getMatchValues()
const
104 return std::vector<ScDPItemData>();
116 virtual std::vector<ScDPItemData>
getMatchValues()
const override;
119 std::vector<ScDPItemData> maValues;
126 ScDPGroupDateFilter::ScDPGroupDateFilter(
128 maValues(
std::move(rValues)),
129 maNullDate(rNullDate),
134 bool ScDPGroupDateFilter::match(
const ScDPItemData & rCellData )
const
137 using ::rtl::math::approxFloor;
138 using ::rtl::math::approxEqual;
148 sal_Int32 nGroupType = rValue.GetGroupValue().mnGroupType;
149 sal_Int32
nValue = rValue.GetGroupValue().mnValue;
154 if (rCellData.
GetValue() < maNumInfo.mfStart && !approxEqual(rCellData.
GetValue(), maNumInfo.mfStart))
161 if (rCellData.
GetValue() > maNumInfo.mfEnd && !approxEqual(rCellData.
GetValue(), maNumInfo.mfEnd))
168 if (nGroupType == DataPilotFieldGroupBy::HOURS || nGroupType == DataPilotFieldGroupBy::MINUTES ||
169 nGroupType == DataPilotFieldGroupBy::SECONDS)
174 sal_uInt16 nHour, nMinute, nSecond;
175 double fFractionOfSecond;
180 case DataPilotFieldGroupBy::HOURS:
186 case DataPilotFieldGroupBy::MINUTES:
188 if (nMinute == nValue)
192 case DataPilotFieldGroupBy::SECONDS:
194 if (nSecond == nValue)
199 OSL_FAIL(
"invalid time part");
205 Date date = maNullDate +
static_cast<sal_Int32
>(approxFloor(rCellData.
GetValue()));
208 case DataPilotFieldGroupBy::YEARS:
210 sal_Int32
year =
static_cast<sal_Int32
>(date.
GetYear());
215 case DataPilotFieldGroupBy::QUARTERS:
217 sal_Int32 qtr = 1 + (
static_cast<sal_Int32
>(date.
GetMonth()) - 1) / 3;
222 case DataPilotFieldGroupBy::MONTHS:
229 case DataPilotFieldGroupBy::DAYS:
232 sal_Int32 days = (date - yearStart) + 1;
243 OSL_FAIL(
"invalid date part");
250 std::vector<ScDPItemData> ScDPGroupDateFilter::getMatchValues()
const
252 return std::vector<ScDPItemData>();
271 return nGroupValue == nChildValue;
276 case css::sheet::DataPilotFieldGroupBy::MONTHS:
278 if (nGroupPart == css::sheet::DataPilotFieldGroupBy::QUARTERS)
280 return (nGroupValue - 1 == (nChildValue - 1) / 3);
282 case css::sheet::DataPilotFieldGroupBy::DAYS:
284 if (nGroupPart == css::sheet::DataPilotFieldGroupBy::MONTHS ||
285 nGroupPart == css::sheet::DataPilotFieldGroupBy::QUARTERS)
288 aDate.AddDays(nChildValue - 1);
289 sal_Int32 nCompare = aDate.GetMonth();
290 if (nGroupPart == css::sheet::DataPilotFieldGroupBy::QUARTERS)
291 nCompare = ( ( nCompare - 1 ) / 3 ) + 1;
293 return nGroupValue == nCompare;
318 [&rData](
const ScDPItemData& rElement) {
return rElement.IsCaseInsEqual(rData); });
334 nSourceDim( nSource ),
336 aGroupName( rNewName ),
337 mbDateDimension(
false)
347 nSourceDim( rOther.nSourceDim ),
348 nGroupDim( rOther.nGroupDim ),
349 aGroupName( rOther.aGroupName ),
350 aItems( rOther.aItems ),
351 mbDateDimension(rOther.mbDateDimension)
367 aItems.push_back( rItem );
388 [&rData](
const ScDPGroupItem& rItem) {
return rItem.HasElement(rData); });
389 if (aIter !=
aItems.end())
398 [&rName](
const ScDPGroupItem& rItem) {
return rItem.GetName().IsCaseInsEqual(rName); });
399 if (aIter !=
aItems.end())
407 if (nIndex >=
aItems.size())
426 aGroupInfo(rInfo), mbDateDimension(
false) {}
429 aGroupInfo(rOther.aGroupInfo), mbDateDimension(rOther.mbDateDimension) {}
466 pSourceData( pSource ),
469 OSL_ENSURE( pSource,
"ScDPGroupTableData: pSource can't be NULL" );
484 aGroups.push_back( aNewGroup );
523 return members.size();
601 rGroup.DisposeData();
611 pSourceData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
626 class FindCaseInsensitive
630 explicit FindCaseInsensitive(
const ScDPItemData& rVal) : maValue(rVal) {}
643 typedef std::unordered_map<tools::Long, const ScDPGroupDimension*> GroupFieldMapType;
644 GroupFieldMapType aGroupFieldIds;
646 for (
const auto& rGroup :
aGroups)
648 aGroupFieldIds.emplace(rGroup.GetGroupDim(), &rGroup);
651 vector<ScDPFilteredCache::Criterion> aNewCriteria;
652 aNewCriteria.reserve(rCriteria.size() + aGroups.size());
657 GroupFieldMapType::const_iterator itrGrpEnd = aGroupFieldIds.end();
658 for (
const auto& rCriterion : rCriteria)
660 std::vector<ScDPItemData> aMatchValues = rCriterion.mpFilter->getMatchValues();
662 GroupFieldMapType::const_iterator itrGrp = aGroupFieldIds.find(rCriterion.mnFieldIndex);
663 if (itrGrp == itrGrpEnd)
681 std::make_shared<ScDPGroupDateFilter>(
688 std::make_shared<ScDPGroupNumFilter>(std::move(aMatchValues), *pNumInfo);
691 aNewCriteria.push_back(aCri);
696 aNewCriteria.push_back(rCriterion);
714 std::make_shared<ScDPGroupDateFilter>(
717 aNewCriteria.push_back(aCri);
725 aCri.
mpFilter = std::make_shared<ScDPFilteredCache::GroupFilter>();
730 for (
size_t i = 0;
i < nGroupItemCount; ++
i)
737 if (std::none_of(aMatchValues.begin(), aMatchValues.end(), FindCaseInsensitive(pGrpItem->
GetName())))
743 aNewCriteria.push_back(aCri);
747 rCriteria.swap(aNewCriteria);
753 pSourceData->FilterCacheTable(std::move(rCriteria), std::move(rCatDims));
759 pSourceData->GetDrillDownData(std::move(rCriteria), std::move(rCatDims),
rData);
769 sal_Int32 nRowSize = rCacheTable.
getRowSize();
770 for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
805 sal_Int32 nGroupedColumns =
aGroups.size();
811 bool bDateDim =
false;
813 sal_Int32 nSourceDim = nColumn;
834 bDateDim =
pNumGroups[nColumn].IsDateDimension();
853 if (bDateDim && pNumInfo)
862 pData->
GetValue(), pNumInfo, nDatePart, pFormatter);
882 [&nGroupDim](
const ScDPGroupDimension& rDim) {
return rDim.GetGroupDim() == nGroupDim; });
884 return aIter->GetSourceDim();
895 return pNumGroups[nDimension].GetInfo().mbEnable ||
900 [&nDimension](
const ScDPGroupDimension& rDim) {
return rDim.GetGroupDim() == nDimension; });
902 return aIter->IsDateDimension();
908 const ScDPItemData& rBaseData, sal_Int32 nBaseIndex )
const
912 return rDim.GetGroupDim() == nGroupIndex && rDim.GetSourceDim() == nBaseIndex; });
918 return isDateInGroup(rGroupData, rBaseData);
931 OSL_FAIL(
"IsInGroup: no group dimension found");
936 const ScDPItemData& rSecondData, sal_Int32 nSecondIndex )
const
940 for (
const auto& rDim :
aGroups )
948 if ( pFirstDim && pSecondDim )
952 if (bFirstDate || bSecondDate)
955 if (!bFirstDate || !bSecondDate)
957 OSL_FAIL(
"mix of date and non-date groups" );
961 return isDateInGroup(rFirstData, rSecondData);
966 if ( pFirstItem && pSecondItem )
971 else if ( pFirstItem )
976 else if ( pSecondItem )
988 OSL_FAIL(
"HasCommonElement: no group dimension found");
1010 if (rItem1 ==
nullptr || rItem2 ==
nullptr)
1015 #if DUMP_PIVOT_TABLE
1019 cout <<
"--- ScDPGroupTableData" <<
endl;
1022 cout <<
"* dimension: " <<
i << endl;
1026 cout <<
"---" << endl;
void GetNumGroupInfo(tools::Long nDimension, ScDPNumGroupInfo &rInfo)
void FillGroupValues(std::vector< SCROW > &rItems, const std::vector< sal_Int32 > &rDims)
virtual void CalcResults(CalcInfo &rInfo, bool bAutoShow) override
const sal_uInt16 SC_DP_LEAPYEAR
const ScDPNumGroupInfo & GetInfo() const
void AddGroupDimension(const ScDPGroupDimension &rGroup)
const std::vector< SCROW > & GetColumnEntries(const ScDPFilteredCache &rCacheTable) const
sal_Int32 getRowSize() const
virtual bool IsNumOrDateGroup(sal_Int32 nDim) const override
std::unique_ptr< sal_Int32[]> pData
ScDPGroupTableData(const std::shared_ptr< ScDPTableData > &pSource, ScDocument *pDocument)
SCROW GetIdByItemData(tools::Long nDim, const ScDPItemData &rItem) const
bool HasElement(const ScDPItemData &rData) const
std::vector< ScDPGroupDimension > aGroups
std::vector< ScDPGroupItem > aItems
PyObject_HEAD PyUNO_callable_Internals * members
::std::vector< sal_Int32 > aRowLevelDims
const ContentProperties & rData
virtual ~ScDPGroupTableData() override
This class represents the cached data part of the datapilot cache table implementation.
std::unique_ptr< ScDPNumGroupDimension[]> pNumGroups
virtual void FilterCacheTable(std::vector< ScDPFilteredCache::Criterion > &&rCriteria, std::unordered_set< sal_Int32 > &&rDataDims) override
virtual void Dump() const override
bool IsNumGroupDimension(tools::Long nDimension) const
interface class used for filtering of rows.
tools::Long GetGroupDim() const
void SetNumGroupDimension(sal_Int32 nIndex, const ScDPNumGroupDimension &rGroup)
virtual sal_Int32 GetSourceDim(sal_Int32 nDim) override
sal_uInt16 GetMonth() const
sal_Int32 GetGroupType(tools::Long nDim) const
Return a group type identifier.
multi-item (group) filter.
const ScDPItemData * GetItemDataById(tools::Long nDim, SCROW nId) const
static sal_Int32 Compare(const ScDPItemData &rA, const ScDPItemData &rB)
std::shared_ptr< FilterBase > mpFilter
static double getNumGroupStartValue(double fValue, const ScDPNumGroupInfo &rInfo)
virtual bool IsBaseForGroup(sal_Int32 nDim) const override
const ScDPNumGroupInfo * GetNumGroupInfo(tools::Long nDim) const
bool isRowActive(sal_Int32 nRow, sal_Int32 *pLastRow=nullptr) const
Check whether a specified row is active or not.
bool IsDateDimension() const
::std::vector< sal_Int32 > aColLevelDims
constexpr OUStringLiteral aData
sal_Int16 GetYear() const
::std::vector< sal_Int32 > aPageDims
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
virtual bool HasCommonElement(const ScDPItemData &rFirstData, sal_Int32 nFirstIndex, const ScDPItemData &rSecondData, sal_Int32 nSecondIndex) const override
virtual const std::vector< SCROW > & GetColumnEntries(sal_Int32 nColumn) override
When assigning a string value, you can also assign an interned string whose life-cycle is managed by ...
void AddElement(const ScDPItemData &rName)
const ScDPGroupItem * GetGroupByIndex(size_t nIndex) const
This structure stores dimension information used when calculating results.
ScDPGroupItem(const ScDPItemData &rName)
virtual sal_Int32 Compare(sal_Int32 nDim, sal_Int32 nDataId1, sal_Int32 nDataId2) override
virtual bool IsDateDimension(sal_Int32 nDim) override
virtual sal_Int32 GetGroupBase(sal_Int32 nGroupDim) const override
tools::Long GetSourceDim() const
::std::vector< SCROW > aRowData
virtual void CreateCacheTable() override
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
GroupValueAttr GetGroupValue() const
std::vector< SCROW > maMemberEntries
static void ProcessRowData(CalcInfo &rInfo, const CalcRowData &rData, bool bAutoShow)
void FillGroupFilter(ScDPFilteredCache::GroupFilter &rFilter) const
ScDPNumGroupDimension & operator=(const ScDPNumGroupDimension &rOther)
sal_Int32 GetDimensionIndex(std::u16string_view rName)
virtual void ReloadCacheTable() override
virtual sal_Int32 GetMembersCount(sal_Int32 nDim) override
ScDPGroupDimension(tools::Long nSource, const OUString &rNewName)
virtual void DisposeData() override
virtual bool match(const ScDPItemData &rCellData) const =0
returns true if the matching condition is met for a single cell value, or false otherwise.
::std::vector< SCROW > aColData
void FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPFilteredCache &rCacheTable, const CalcInfo &rInfo, CalcRowData &rData)
virtual sal_Int32 GetColumnCount() override
use (new) typed collection instead of ScStrCollection or separate Str and ValueCollection ...
void addMatchItem(const ScDPItemData &rItem)
virtual sal_uInt32 GetNumberFormat(sal_Int32 nDim) override
std::vector< SCROW > maMemberEntries
virtual std::vector< ScDPItemData > getMatchValues() const =0
void AddItem(const ScDPGroupItem &rItem)
std::shared_ptr< ScDPTableData > pSourceData
virtual const ScDPItemData * GetMemberById(sal_Int32 nDim, sal_Int32 nId) override
Base class that abstracts different data source types of a datapilot table.
single filtering criterion.
This structure stores vector arrays that hold intermediate data for each row during cache table itera...
static const sal_Int32 DateLast
::std::vector< SCROW > aPageData
virtual void SetEmptyFlags(bool bIgnoreEmptyRows, bool bRepeatIfEmpty) override
SvStream & endl(SvStream &rStr)
static const sal_Int32 DateFirst
bool HasCommonElement(const ScDPGroupItem &rOther) const
static sal_Int32 getDatePartValue(double fValue, const ScDPNumGroupInfo *pInfo, sal_Int32 nDatePart, const SvNumberFormatter *pFormatter)
ScDPGroupDimension & operator=(const ScDPGroupDimension &rOther)
const std::vector< SCROW > & GetNumEntries(SCCOL nSourceDim, const ScDPCache *pCache) const
ScDPItemDataVec aElements
void ModifyFilterCriteria(::std::vector< ScDPFilteredCache::Criterion > &rCriteria)
ScDPNumGroupInfo aGroupInfo
const ScDPGroupItem * GetGroupForData(const ScDPItemData &rData) const
void SetGroupDim(tools::Long nDim)
virtual bool getIsDataLayoutDimension(sal_Int32 nColumn) override
This class is only a wrapper to the actual cache, to provide filtering on the raw data based on the q...
bool IsCaseInsEqual(const ScDPItemData &r) const
void GetGroupDimMemberIds(tools::Long nDim, std::vector< SCROW > &rIds) const
virtual const ScDPFilteredCache & GetCacheTable() const override
const ScDPGroupItem * GetGroupForName(const ScDPItemData &rName) const
virtual OUString getDimensionName(sal_Int32 nColumn) override
size_t GetItemCount() const
const ScDPCache & getCache() const
bool m_bDetectedRangeSegmentation false
const ScDPItemData & GetName() const
bool IsDateDimension() const
virtual bool IsRepeatIfEmpty() override
void SetRangeStart(double fVal)