initial support for percentile in data bars/color scales

Color Scales look correctly but in the databar code seems to be an error
if all values are positive.

Change-Id: I0bfb277df50021bd20a4b13a5da342670102b649
This commit is contained in:
Markus Mohrhard
2012-05-21 15:47:23 +02:00
parent 4857923746
commit f654980aeb
4 changed files with 109 additions and 19 deletions

View File

@@ -32,6 +32,8 @@
#include <tools/color.hxx> #include <tools/color.hxx>
#include <rangelst.hxx> #include <rangelst.hxx>
#include <vector>
//TODO: merge this with conditio.hxx //TODO: merge this with conditio.hxx
class ScDocument; class ScDocument;
@@ -49,6 +51,7 @@ private:
bool mbMin; bool mbMin;
bool mbMax; bool mbMax;
bool mbPercent; bool mbPercent;
bool mbPercentile;
public: public:
ScColorScaleEntry(double nVal, const Color& rCol); ScColorScaleEntry(double nVal, const Color& rCol);
ScColorScaleEntry(const ScColorScaleEntry& rEntry); ScColorScaleEntry(const ScColorScaleEntry& rEntry);
@@ -65,11 +68,13 @@ public:
bool GetMin() const; bool GetMin() const;
bool GetMax() const; bool GetMax() const;
bool GetPercent() const; bool GetPercent() const;
bool GetPercentile() const;
bool HasFormula() const; bool HasFormula() const;
const ScTokenArray* GetFormula() const; const ScTokenArray* GetFormula() const;
void SetMin(bool bMin); void SetMin(bool bMin);
void SetMax(bool bMax); void SetMax(bool bMax);
void SetPercent(bool bPercent); void SetPercent(bool bPercent);
void SetPercentile(bool bPercentile);
}; };
namespace databar namespace databar
@@ -160,6 +165,8 @@ public:
virtual ScColorFormatType GetType() const = 0; virtual ScColorFormatType GetType() const = 0;
protected: protected:
void getValues( std::vector<double>& rValues ) const;
ScRangeList maRanges; ScRangeList maRanges;
ScDocument* mpDoc; ScDocument* mpDoc;
}; };
@@ -175,6 +182,7 @@ private:
void calcMinMax(double& nMin, double& nMax) const; void calcMinMax(double& nMin, double& nMax) const;
bool CheckEntriesForRel(const ScRange& rRange) const; bool CheckEntriesForRel(const ScRange& rRange) const;
double CalcValue(double nMin, double nMax, ColorScaleEntries::const_iterator& rItr) const;
public: public:
ScColorScaleFormat(ScDocument* pDoc); ScColorScaleFormat(ScDocument* pDoc);
ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat); ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat);

View File

@@ -37,7 +37,8 @@ ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol):
mpCell(NULL), mpCell(NULL),
mbMin(false), mbMin(false),
mbMax(false), mbMax(false),
mbPercent(false) mbPercent(false),
mbPercentile(false)
{ {
} }
@@ -47,7 +48,8 @@ ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry& rEntry):
mpCell(), mpCell(),
mbMin(rEntry.mbMin), mbMin(rEntry.mbMin),
mbMax(rEntry.mbMax), mbMax(rEntry.mbMax),
mbPercent(rEntry.mbPercent) mbPercent(rEntry.mbPercent),
mbPercentile(rEntry.mbPercentile)
{ {
} }
@@ -57,7 +59,8 @@ ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, const ScColorScaleEntry&
mpCell(), mpCell(),
mbMin(rEntry.mbMin), mbMin(rEntry.mbMin),
mbMax(rEntry.mbMax), mbMax(rEntry.mbMax),
mbPercent(rEntry.mbPercent) mbPercent(rEntry.mbPercent),
mbPercentile(rEntry.mbPercentile)
{ {
if(rEntry.mpCell) if(rEntry.mpCell)
{ {
@@ -179,6 +182,11 @@ bool ScColorScaleEntry::GetPercent() const
return mbPercent; return mbPercent;
} }
bool ScColorScaleEntry::GetPercentile() const
{
return mbPercentile;
}
bool ScColorScaleEntry::HasFormula() const bool ScColorScaleEntry::HasFormula() const
{ {
return mpCell; return mpCell;
@@ -199,6 +207,11 @@ void ScColorScaleEntry::SetPercent(bool bPercent)
mbPercent = bPercent; mbPercent = bPercent;
} }
void ScColorScaleEntry::SetPercentile(bool bPercentile)
{
mbPercentile = bPercentile;
}
namespace { namespace {
double getMinValue(const ScRange& rRange, ScDocument* pDoc) double getMinValue(const ScRange& rRange, ScDocument* pDoc)
@@ -336,6 +349,37 @@ const ScRangeList& ScColorFormat::GetRange() const
return maRanges; return maRanges;
} }
void ScColorFormat::getValues(std::vector<double>& rValues) const
{
size_t n = maRanges.size();
for(size_t i = 0; i < n; ++i)
{
const ScRange* pRange = maRanges[i];
SCTAB nTab = pRange->aStart.Tab();
for(SCCOL nCol = pRange->aStart.Col(); nCol <= pRange->aEnd.Col(); ++nCol)
{
for(SCCOL nRow = pRange->aStart.Row(); nRow <= pRange->aEnd.Row(); ++nRow)
{
ScAddress aAddr(nCol, nRow, nTab);
CellType eType = mpDoc->GetCellType(aAddr);
if(eType == CELLTYPE_VALUE)
{
double aVal = mpDoc->GetValue(nCol, nRow, nTab);
rValues.push_back(aVal);
}
else if(eType == CELLTYPE_FORMULA)
{
if(static_cast<ScFormulaCell*>(mpDoc->GetCell(aAddr))->IsValue())
{
double aVal = mpDoc->GetValue(nCol, nRow, nTab);
rValues.push_back(aVal);
}
}
}
}
}
}
namespace { namespace {
sal_uInt8 GetColorValue( double nVal, double nVal1, sal_uInt8 nColVal1, double nVal2, sal_uInt8 nColVal2 ) sal_uInt8 GetColorValue( double nVal, double nVal1, sal_uInt8 nColVal1, double nVal2, sal_uInt8 nColVal2 )
@@ -359,7 +403,27 @@ Color CalcColor( double nVal, double nVal1, const Color& rCol1, double nVal2, co
return Color(nColRed, nColGreen, nColBlue); return Color(nColRed, nColGreen, nColBlue);
} }
double CalcValue(double nMin, double nMax, ScColorScaleFormat::const_iterator& itr) double GetPercentile( std::vector<double>& rArray, double fPercentile )
{
size_t nSize = rArray.size();
size_t nIndex = (size_t)::rtl::math::approxFloor( fPercentile * (nSize-1));
double fDiff = fPercentile * (nSize-1) - ::rtl::math::approxFloor( fPercentile * (nSize-1));
std::vector<double>::iterator iter = rArray.begin() + nIndex;
::std::nth_element( rArray.begin(), iter, rArray.end());
if (fDiff == 0.0)
return *iter;
else
{
double fVal = *iter;
iter = rArray.begin() + nIndex+1;
::std::nth_element( rArray.begin(), iter, rArray.end());
return fVal + fDiff * (*iter - fVal);
}
}
}
double ScColorScaleFormat::CalcValue(double nMin, double nMax, ScColorScaleFormat::const_iterator& itr) const
{ {
if(itr->GetPercent()) if(itr->GetPercent())
{ {
@@ -373,12 +437,22 @@ double CalcValue(double nMin, double nMax, ScColorScaleFormat::const_iterator& i
{ {
return nMax; return nMax;
} }
else if(itr->GetPercentile())
{
std::vector<double> aValues;
getValues(aValues);
if(aValues.size() == 1)
return aValues[0];
else
{
double fPercentile = itr->GetValue()/100.0;
return GetPercentile(aValues, fPercentile);
}
}
return itr->GetValue(); return itr->GetValue();
} }
}
Color* ScColorScaleFormat::GetColor( const ScAddress& rAddr ) const Color* ScColorScaleFormat::GetColor( const ScAddress& rAddr ) const
{ {
CellType eCellType = mpDoc->GetCellType(rAddr); CellType eCellType = mpDoc->GetCellType(rAddr);
@@ -638,10 +712,14 @@ double ScDataBarFormat::getMin(double nMin, double nMax) const
{ {
if(mpFormatData->mpLowerLimit->GetMin()) if(mpFormatData->mpLowerLimit->GetMin())
return nMin; return nMin;
else if(mpFormatData->mpLowerLimit->GetPercent())
if(mpFormatData->mpLowerLimit->GetPercent())
{
return nMin + (nMax-nMin)/100*mpFormatData->mpLowerLimit->GetValue(); return nMin + (nMax-nMin)/100*mpFormatData->mpLowerLimit->GetValue();
else if(mpFormatData->mpLowerLimit->GetPercentile())
{
double fPercentile = mpFormatData->mpLowerLimit->GetValue()/100.0;
std::vector<double> aValues;
getValues(aValues);
return GetPercentile(aValues, fPercentile);
} }
return mpFormatData->mpLowerLimit->GetValue(); return mpFormatData->mpLowerLimit->GetValue();
@@ -651,10 +729,14 @@ double ScDataBarFormat::getMax(double nMin, double nMax) const
{ {
if(mpFormatData->mpUpperLimit->GetMax()) if(mpFormatData->mpUpperLimit->GetMax())
return nMax; return nMax;
else if(mpFormatData->mpUpperLimit->GetPercent())
if(mpFormatData->mpUpperLimit->GetPercent())
{
return nMin + (nMax-nMin)/100*mpFormatData->mpUpperLimit->GetValue(); return nMin + (nMax-nMin)/100*mpFormatData->mpUpperLimit->GetValue();
else if(mpFormatData->mpLowerLimit->GetPercentile())
{
double fPercentile = mpFormatData->mpLowerLimit->GetValue()/100.0;
std::vector<double> aValues;
getValues(aValues);
return GetPercentile(aValues, fPercentile);
} }
return mpFormatData->mpUpperLimit->GetValue(); return mpFormatData->mpUpperLimit->GetValue();

View File

@@ -86,6 +86,7 @@ struct ColorScaleRuleModelEntry
bool mbMin; bool mbMin;
bool mbMax; bool mbMax;
bool mbPercent; bool mbPercent;
bool mbPercentile;
rtl::OUString maFormula; rtl::OUString maFormula;
ColorScaleRuleModelEntry(): ColorScaleRuleModelEntry():
@@ -93,7 +94,8 @@ struct ColorScaleRuleModelEntry
mnVal(0), mnVal(0),
mbMin(false), mbMin(false),
mbMax(false), mbMax(false),
mbPercent(false) {} mbPercent(false),
mbPercentile(false) {}
}; };
class ColorScaleRule : public WorksheetHelper class ColorScaleRule : public WorksheetHelper

View File

@@ -178,9 +178,7 @@ void ColorScaleRule::importCfvo( const AttributeList& rAttribs )
} }
else if( aType == "percentile" ) else if( aType == "percentile" )
{ {
// this is most likely wrong but I have no idea what the difference maColorScaleRuleEntries[mnCfvo].mbPercentile = true;
// between percent and percentile should be when calculating colors
maColorScaleRuleEntries[mnCfvo].mbPercent = true;
} }
else if( aType == "formula" ) else if( aType == "formula" )
{ {
@@ -236,6 +234,8 @@ ScColorScaleEntry* ConvertToModel( const ColorScaleRuleModelEntry& rEntry, ScDoc
pEntry->SetMax(true); pEntry->SetMax(true);
if(rEntry.mbPercent) if(rEntry.mbPercent)
pEntry->SetPercent(true); pEntry->SetPercent(true);
if(rEntry.mbPercentile)
pEntry->SetPercentile(true);
if(!rEntry.maFormula.isEmpty()) if(!rEntry.maFormula.isEmpty())
pEntry->SetFormula(rEntry.maFormula, pDoc, rAddr, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1); pEntry->SetFormula(rEntry.maFormula, pDoc, rAddr, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
@@ -318,9 +318,7 @@ void DataBarRule::importCfvo( const AttributeList& rAttribs )
} }
else if( aType == "percentile" ) else if( aType == "percentile" )
{ {
// this is most likely wrong but I have no idea what the difference pEntry->mbPercentile = true;
// between percent and percentile should be when calculating colors
pEntry->mbPercent = true;
} }
else if( aType == "formula" ) else if( aType == "formula" )
{ {