summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-07-13 16:59:16 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-07-13 17:01:15 -0400
commit76488b00ed75bf7915d6d57af9875c6434e740d6 (patch)
treee05058dde4a99c0fbd3a22228da45b2f075d9525
parentd9bfa462ba8dd0a966fe913fad49f300ea48f638 (diff)
fdo#63998: Filtering by page fields to work again.
Change-Id: I267ccb30cfa6347313fa1de96e18731f0e22d57d
-rw-r--r--sc/inc/dpfilteredcache.hxx5
-rw-r--r--sc/source/core/data/dpfilteredcache.cxx12
-rw-r--r--sc/source/core/data/dpgroup.cxx296
3 files changed, 197 insertions, 116 deletions
diff --git a/sc/inc/dpfilteredcache.hxx b/sc/inc/dpfilteredcache.hxx
index bff1e181e7a7..e6c9bd0dc7c5 100644
--- a/sc/inc/dpfilteredcache.hxx
+++ b/sc/inc/dpfilteredcache.hxx
@@ -56,6 +56,8 @@ public:
/** returns true if the matching condition is met for a single cell
value, or false otherwise. */
virtual bool match( const ScDPItemData& rCellData ) const = 0;
+
+ virtual std::vector<ScDPItemData> getMatchValues() const = 0;
};
/** ordinary single-item filter. */
@@ -66,7 +68,7 @@ public:
virtual ~SingleFilter() {}
virtual bool match(const ScDPItemData& rCellData) const;
-
+ virtual std::vector<ScDPItemData> getMatchValues() const;
const ScDPItemData& getMatchValue() const;
private:
@@ -82,6 +84,7 @@ public:
GroupFilter();
virtual ~GroupFilter() {}
virtual bool match(const ScDPItemData& rCellData) const;
+ virtual std::vector<ScDPItemData> getMatchValues() const;
void addMatchItem(const ScDPItemData& rItem);
size_t getMatchItemCount() const;
diff --git a/sc/source/core/data/dpfilteredcache.cxx b/sc/source/core/data/dpfilteredcache.cxx
index 51bf57116391..62c33eb11397 100644
--- a/sc/source/core/data/dpfilteredcache.cxx
+++ b/sc/source/core/data/dpfilteredcache.cxx
@@ -62,6 +62,13 @@ bool ScDPFilteredCache::SingleFilter::match(const ScDPItemData& rCellData) const
return maItem == rCellData;
}
+std::vector<ScDPItemData> ScDPFilteredCache::SingleFilter::getMatchValues() const
+{
+ std::vector<ScDPItemData> aValues;
+ aValues.push_back(maItem);
+ return aValues;
+}
+
const ScDPItemData& ScDPFilteredCache::SingleFilter::getMatchValue() const
{
return maItem;
@@ -83,6 +90,11 @@ bool ScDPFilteredCache::GroupFilter::match(const ScDPItemData& rCellData) const
return false;
}
+std::vector<ScDPItemData> ScDPFilteredCache::GroupFilter::getMatchValues() const
+{
+ return maItems;
+}
+
void ScDPFilteredCache::GroupFilter::addMatchItem(const ScDPItemData& rItem)
{
maItems.push_back(rItem);
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 5368523f5c61..81920d840efa 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -54,41 +54,54 @@ const sal_uInt16 SC_DP_LEAPYEAR = 1648; // arbitrary leap year for date calc
class ScDPGroupNumFilter : public ScDPFilteredCache::FilterBase
{
public:
- ScDPGroupNumFilter(const ScDPItemData& rValue, const ScDPNumGroupInfo& rInfo);
+ ScDPGroupNumFilter(const std::vector<ScDPItemData>& rValues, const ScDPNumGroupInfo& rInfo);
virtual ~ScDPGroupNumFilter() {}
virtual bool match(const ScDPItemData &rCellData) const;
+ virtual std::vector<ScDPItemData> getMatchValues() const;
private:
- ScDPItemData maValue;
+ std::vector<ScDPItemData> maValues;
ScDPNumGroupInfo maNumInfo;
};
-ScDPGroupNumFilter::ScDPGroupNumFilter(const ScDPItemData& rValue, const ScDPNumGroupInfo& rInfo) :
- maValue(rValue), maNumInfo(rInfo) {}
+ScDPGroupNumFilter::ScDPGroupNumFilter(const std::vector<ScDPItemData>& rValues, const ScDPNumGroupInfo& rInfo) :
+ maValues(rValues), maNumInfo(rInfo) {}
bool ScDPGroupNumFilter::match(const ScDPItemData& rCellData) const
{
if (rCellData.GetType() != ScDPItemData::Value)
return false;
- double fVal = maValue.GetValue();
- if (rtl::math::isInf(fVal))
+ std::vector<ScDPItemData>::const_iterator it = maValues.begin(), itEnd = maValues.end();
+ for (; it != itEnd; ++it)
{
- if (rtl::math::isSignBitSet(fVal))
+ double fVal = it->GetValue();
+ if (rtl::math::isInf(fVal))
{
- // Less than the min value.
- return rCellData.GetValue() < maNumInfo.mfStart;
+ if (rtl::math::isSignBitSet(fVal))
+ {
+ // Less than the min value.
+ return rCellData.GetValue() < maNumInfo.mfStart;
+ }
+
+ // Greater than the max value.
+ return maNumInfo.mfEnd < rCellData.GetValue();
}
- // Greater than the max value.
- return maNumInfo.mfEnd < rCellData.GetValue();
+ double low = fVal;
+ double high = low + maNumInfo.mfStep;
+ if (maNumInfo.mbIntegerOnly)
+ high += 1.0;
+
+ if (low <= rCellData.GetValue() && rCellData.GetValue() < high)
+ return true;
}
- double low = fVal;
- double high = low + maNumInfo.mfStep;
- if (maNumInfo.mbIntegerOnly)
- high += 1.0;
+ return false;
+}
- return low <= rCellData.GetValue() && rCellData.GetValue() < high;
+std::vector<ScDPItemData> ScDPGroupNumFilter::getMatchValues() const
+{
+ return std::vector<ScDPItemData>();
}
class ScDPGroupDateFilter : public ScDPFilteredCache::FilterBase
@@ -96,14 +109,15 @@ class ScDPGroupDateFilter : public ScDPFilteredCache::FilterBase
public:
virtual ~ScDPGroupDateFilter() {}
ScDPGroupDateFilter(
- const ScDPItemData& rValue, const Date& rNullDate, const ScDPNumGroupInfo& rNumInfo);
+ const std::vector<ScDPItemData>& rValues, const Date& rNullDate, const ScDPNumGroupInfo& rNumInfo);
virtual bool match(const ScDPItemData & rCellData) const;
+ virtual std::vector<ScDPItemData> getMatchValues() const;
private:
ScDPGroupDateFilter(); // disabled
- ScDPItemData maValue;
+ std::vector<ScDPItemData> maValues;
Date maNullDate;
ScDPNumGroupInfo maNumInfo;
};
@@ -111,8 +125,8 @@ private:
// ----------------------------------------------------------------------------
ScDPGroupDateFilter::ScDPGroupDateFilter(
- const ScDPItemData& rItem, const Date& rNullDate, const ScDPNumGroupInfo& rNumInfo) :
- maValue(rItem),
+ const std::vector<ScDPItemData>& rValues, const Date& rNullDate, const ScDPNumGroupInfo& rNumInfo) :
+ maValues(rValues),
maNullDate(rNullDate),
maNumInfo(rNumInfo)
{
@@ -127,94 +141,122 @@ bool ScDPGroupDateFilter::match( const ScDPItemData & rCellData ) const
if ( !rCellData.IsValue() )
return false;
- if (maValue.GetType() != ScDPItemData::GroupValue)
- return false;
+ std::vector<ScDPItemData>::const_iterator it = maValues.begin(), itEnd = maValues.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScDPItemData& rValue = *it;
+ if (rValue.GetType() != ScDPItemData::GroupValue)
+ continue;
- sal_Int32 nGroupType = maValue.GetGroupValue().mnGroupType;
- sal_Int32 nValue = maValue.GetGroupValue().mnValue;
+ sal_Int32 nGroupType = rValue.GetGroupValue().mnGroupType;
+ sal_Int32 nValue = rValue.GetGroupValue().mnValue;
- // Start and end dates are inclusive. (An end date without a time value
- // is included, while an end date with a time value is not.)
+ // Start and end dates are inclusive. (An end date without a time value
+ // is included, while an end date with a time value is not.)
- if ( rCellData.GetValue() < maNumInfo.mfStart && !approxEqual(rCellData.GetValue(), maNumInfo.mfStart) )
- {
- return nValue == ScDPItemData::DateFirst;
- }
+ if (rCellData.GetValue() < maNumInfo.mfStart && !approxEqual(rCellData.GetValue(), maNumInfo.mfStart))
+ {
+ if (nValue == ScDPItemData::DateFirst)
+ return true;
+ continue;
+ }
- if ( rCellData.GetValue() > maNumInfo.mfEnd && !approxEqual(rCellData.GetValue(), maNumInfo.mfEnd) )
- {
- return nValue == ScDPItemData::DateLast;
- }
+ if (rCellData.GetValue() > maNumInfo.mfEnd && !approxEqual(rCellData.GetValue(), maNumInfo.mfEnd))
+ {
+ if (nValue == ScDPItemData::DateLast)
+ return true;
+ continue;
+ }
+ if (nGroupType == DataPilotFieldGroupBy::HOURS || nGroupType == DataPilotFieldGroupBy::MINUTES ||
+ nGroupType == DataPilotFieldGroupBy::SECONDS)
+ {
+ // handle time
+ // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds are rounded)
- if (nGroupType == DataPilotFieldGroupBy::HOURS || nGroupType == DataPilotFieldGroupBy::MINUTES ||
- nGroupType == DataPilotFieldGroupBy::SECONDS)
- {
- // handle time
- // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds are rounded)
+ double time = rCellData.GetValue() - approxFloor(rCellData.GetValue());
+ long seconds = static_cast<long>(approxFloor(time*DATE_TIME_FACTOR + 0.5));
+
+ switch (nGroupType)
+ {
+ case DataPilotFieldGroupBy::HOURS:
+ {
+ sal_Int32 hrs = seconds / 3600;
+ if (hrs == nValue)
+ return true;
+ }
+ break;
+ case DataPilotFieldGroupBy::MINUTES:
+ {
+ sal_Int32 minutes = (seconds % 3600) / 60;
+ if (minutes == nValue)
+ return true;
+ }
+ break;
+ case DataPilotFieldGroupBy::SECONDS:
+ {
+ sal_Int32 sec = seconds % 60;
+ if (sec == nValue)
+ return true;
+ }
+ break;
+ default:
+ OSL_FAIL("invalid time part");
+ }
- double time = rCellData.GetValue() - approxFloor(rCellData.GetValue());
- long seconds = static_cast<long>(approxFloor(time*DATE_TIME_FACTOR + 0.5));
+ continue;
+ }
+ Date date = maNullDate + static_cast<long>(approxFloor(rCellData.GetValue()));
switch (nGroupType)
{
- case DataPilotFieldGroupBy::HOURS:
+ case DataPilotFieldGroupBy::YEARS:
{
- sal_Int32 hrs = seconds / 3600;
- return hrs == nValue;
+ sal_Int32 year = static_cast<sal_Int32>(date.GetYear());
+ if (year == nValue)
+ return true;
}
- case DataPilotFieldGroupBy::MINUTES:
+ break;
+ case DataPilotFieldGroupBy::QUARTERS:
{
- sal_Int32 minutes = (seconds % 3600) / 60;
- return minutes == nValue;
+ sal_Int32 qtr = 1 + (static_cast<sal_Int32>(date.GetMonth()) - 1) / 3;
+ if (qtr == nValue)
+ return true;
}
- case DataPilotFieldGroupBy::SECONDS:
+ break;
+ case DataPilotFieldGroupBy::MONTHS:
{
- sal_Int32 sec = seconds % 60;
- return sec == nValue;
+ sal_Int32 month = static_cast<sal_Int32>(date.GetMonth());
+ if (month == nValue)
+ return true;
}
- default:
- OSL_FAIL("invalid time part");
- }
- return false;
- }
-
- Date date = maNullDate + static_cast<long>(approxFloor(rCellData.GetValue()));
- switch (nGroupType)
- {
- case DataPilotFieldGroupBy::YEARS:
- {
- sal_Int32 year = static_cast<sal_Int32>(date.GetYear());
- return year == nValue;
- }
- case DataPilotFieldGroupBy::QUARTERS:
- {
- sal_Int32 qtr = 1 + (static_cast<sal_Int32>(date.GetMonth()) - 1) / 3;
- return qtr == nValue;
- }
- case DataPilotFieldGroupBy::MONTHS:
- {
- sal_Int32 month = static_cast<sal_Int32>(date.GetMonth());
- return month == nValue;
- }
- case DataPilotFieldGroupBy::DAYS:
- {
- Date yearStart(1, 1, date.GetYear());
- sal_Int32 days = (date - yearStart) + 1; // Jan 01 has value 1
- if (days >= 60 && !date.IsLeapYear())
+ break;
+ case DataPilotFieldGroupBy::DAYS:
{
- // This is not a leap year. Adjust the value accordingly.
- ++days;
+ Date yearStart(1, 1, date.GetYear());
+ sal_Int32 days = (date - yearStart) + 1; // Jan 01 has value 1
+ if (days >= 60 && !date.IsLeapYear())
+ {
+ // This is not a leap year. Adjust the value accordingly.
+ ++days;
+ }
+ if (days == nValue)
+ return true;
}
- return days == nValue;
+ break;
+ default:
+ OSL_FAIL("invalid date part");
}
- default:
- OSL_FAIL("invalid date part");
}
return false;
}
+std::vector<ScDPItemData> ScDPGroupDateFilter::getMatchValues() const
+{
+ return std::vector<ScDPItemData>();
+}
+
namespace {
bool isDateInGroup(const ScDPItemData& rGroupItem, const ScDPItemData& rChildItem)
@@ -616,14 +658,34 @@ void ScDPGroupTableData::CreateCacheTable()
pSourceData->CreateCacheTable();
}
+namespace {
+
+class FindCaseInsensitive : std::unary_function<ScDPItemData, bool>
+{
+ ScDPItemData maValue;
+public:
+ FindCaseInsensitive(const ScDPItemData& rVal) : maValue(rVal) {}
+
+ bool operator() (const ScDPItemData& rItem) const
+ {
+ return maValue.IsCaseInsEqual(rItem);
+ }
+};
+
+}
+
void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterion>& rCriteria)
{
+ // Build dimension ID to object map for group dimensions.
typedef boost::unordered_map<long, const ScDPGroupDimension*> GroupFieldMapType;
GroupFieldMapType aGroupFieldIds;
{
ScDPGroupDimensionVec::const_iterator itr = aGroups.begin(), itrEnd = aGroups.end();
for (; itr != itrEnd; ++itr)
- aGroupFieldIds.insert( boost::unordered_map<long, const ScDPGroupDimension*>::value_type(itr->GetGroupDim(), &(*itr)) );
+ {
+ aGroupFieldIds.insert(
+ GroupFieldMapType::value_type(itr->GetGroupDim(), &(*itr)));
+ }
}
vector<ScDPFilteredCache::Criterion> aNewCriteria;
@@ -636,10 +698,7 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
GroupFieldMapType::const_iterator itrGrpEnd = aGroupFieldIds.end();
for (vector<ScDPFilteredCache::Criterion>::const_iterator itr = rCriteria.begin(); itr != itrEnd; ++itr)
{
- ScDPFilteredCache::SingleFilter* pFilter = dynamic_cast<ScDPFilteredCache::SingleFilter*>(itr->mpFilter.get());
- if (!pFilter)
- // We expect this to be a single filter.
- continue;
+ std::vector<ScDPItemData> aMatchValues = itr->mpFilter->getMatchValues();
GroupFieldMapType::const_iterator itrGrp = aGroupFieldIds.find(itr->mnFieldIndex);
if (itrGrp == itrGrpEnd)
@@ -647,26 +706,27 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
if (IsNumGroupDimension(itr->mnFieldIndex))
{
// internal number group field
+ const ScDPNumGroupInfo* pNumInfo = pCache->GetNumGroupInfo(itr->mnFieldIndex);
+ if (!pNumInfo)
+ // Number group dimension without num info? Something is wrong...
+ continue;
+
ScDPFilteredCache::Criterion aCri;
aCri.mnFieldIndex = itr->mnFieldIndex;
const ScDPNumGroupDimension& rNumGrpDim = pNumGroups[itr->mnFieldIndex];
- const ScDPNumGroupInfo* pNumInfo = pCache->GetNumGroupInfo(itr->mnFieldIndex);
- if (pNumInfo)
+ if (rNumGrpDim.IsDateDimension())
+ {
+ // grouped by dates.
+ aCri.mpFilter.reset(
+ new ScDPGroupDateFilter(
+ aMatchValues, *pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
+ }
+ else
{
- if (rNumGrpDim.IsDateDimension())
- {
- // grouped by dates.
- aCri.mpFilter.reset(
- new ScDPGroupDateFilter(
- pFilter->getMatchValue(), *pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
- }
- else
- {
- // This dimension is grouped by numeric ranges.
- aCri.mpFilter.reset(
- new ScDPGroupNumFilter(pFilter->getMatchValue(), *pNumInfo));
- }
+ // This dimension is grouped by numeric ranges.
+ aCri.mpFilter.reset(
+ new ScDPGroupNumFilter(aMatchValues, *pNumInfo));
}
aNewCriteria.push_back(aCri);
@@ -693,7 +753,7 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
aCri.mnFieldIndex = nSrcDim; // use the source dimension, not the group dimension.
aCri.mpFilter.reset(
new ScDPGroupDateFilter(
- pFilter->getMatchValue(), *pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
+ aMatchValues, *pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
aNewCriteria.push_back(aCri);
}
@@ -701,25 +761,31 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
{
// normal group
- // Note that each group dimension may have multiple group names!
+ ScDPFilteredCache::Criterion aCri;
+ aCri.mnFieldIndex = nSrcDim;
+ aCri.mpFilter.reset(new ScDPFilteredCache::GroupFilter());
+ ScDPFilteredCache::GroupFilter* pGrpFilter =
+ static_cast<ScDPFilteredCache::GroupFilter*>(aCri.mpFilter.get());
+
size_t nGroupItemCount = pGrpDim->GetItemCount();
for (size_t i = 0; i < nGroupItemCount; ++i)
{
const ScDPGroupItem* pGrpItem = pGrpDim->GetGroupByIndex(i);
- ScDPItemData aName = pFilter->getMatchValue();
-
- if (!pGrpItem || !pGrpItem->GetName().IsCaseInsEqual(aName))
+ if (!pGrpItem)
continue;
- ScDPFilteredCache::Criterion aCri;
- aCri.mnFieldIndex = nSrcDim;
- aCri.mpFilter.reset(new ScDPFilteredCache::GroupFilter());
- ScDPFilteredCache::GroupFilter* pGrpFilter =
- static_cast<ScDPFilteredCache::GroupFilter*>(aCri.mpFilter.get());
+ // Make sure this group name equals one of the match values.
+ std::vector<ScDPItemData>::iterator it =
+ std::find_if(
+ aMatchValues.begin(), aMatchValues.end(), FindCaseInsensitive(pGrpItem->GetName()));
+
+ if (it == aMatchValues.end())
+ continue;
pGrpItem->FillGroupFilter(*pGrpFilter);
- aNewCriteria.push_back(aCri);
}
+
+ aNewCriteria.push_back(aCri);
}
}
}