Dynamic autofilter show/hide rows for this/next/last

week/month/quarter/year etc
This commit is contained in:
Mark Baker 2012-08-18 23:41:16 +01:00
parent dc01c8bbc1
commit f9a1267697
5 changed files with 226 additions and 36 deletions

View File

@ -1150,7 +1150,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader
// Custom filters can an AND or an OR join;
// and there should only ever be one or two entries
if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) {
$column->setAndOr(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND);
$column->setJoin(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND);
}
foreach ($customFilters->customFilter as $filterRule) {
$column->createRule()->setRule(
@ -1171,6 +1171,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader
(string) $filterRule["type"]
)
->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
if (isset($filterRule["val"])) {
$column->setAttribute('val',(string) $filterRule["val"]);
}
if (isset($filterRule["maxVal"])) {
$column->setAttribute('maxVal',(string) $filterRule["maxVal"]);
}
}
}
// Check for dynamic filters

View File

@ -292,7 +292,7 @@ class PHPExcel_Worksheet_AutoFilter
return FALSE;
}
$returnVal = ($join == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND);
$returnVal = ($join == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND);
foreach($dataSet as $rule) {
if (is_numeric($rule['value'])) {
// Numeric values are tested using the appropriate operator
@ -322,14 +322,14 @@ class PHPExcel_Worksheet_AutoFilter
}
// If there are multiple conditions, then we need to test both using the appropriate join operator
switch ($join) {
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_OR :
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR :
$returnVal = $returnVal || $retVal;
// Break as soon as we have a TRUE match for OR joins,
// to avoid unnecessary additional code execution
if ($returnVal)
return $returnVal;
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND :
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND :
$returnVal = $returnVal && $retVal;
break;
}
@ -341,6 +341,7 @@ class PHPExcel_Worksheet_AutoFilter
private static function _filterTypeDynamicFilters($cellValue,$testSet)
{
echo 'CALLING _filterTypeDynamicFilters',PHP_EOL;
return TRUE;
}
@ -353,6 +354,121 @@ class PHPExcel_Worksheet_AutoFilter
private static $_fromReplace = array('\*', '\?', '~~', '~.*', '~.?');
private static $_toReplace = array('.*', '.', '~', '\*', '\?');
private function _dynamicFilterDateRange($dynamicRuleType, $filterColumn)
{
$rDateType = PHPExcel_Calculation_Functions::getReturnDateType();
PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC);
$val = $maxVal = NULL;
$ruleValues = array();
$baseDate = PHPExcel_Calculation_DateTime::DATENOW();
switch ($dynamicRuleType) {
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK :
$baseDate = strtotime('-7 days',$baseDate);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK :
$baseDate = strtotime('-7 days',$baseDate);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH :
$baseDate = strtotime('-1 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH :
$baseDate = strtotime('+1 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER :
$baseDate = strtotime('-3 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER :
$baseDate = strtotime('+3 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR :
$baseDate = strtotime('-1 year',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR :
$baseDate = strtotime('+1 year',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
}
switch ($dynamicRuleType) {
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW :
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day',$baseDate));
$val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE :
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day',$baseDate));
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,1,date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR :
$maxVal = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,31,12,date('Y',$baseDate)));
++$maxVal;
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,1,date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER :
$thisMonth = date('m',$baseDate);
$thisQuarter = floor(--$thisMonth / 3);
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0,0,0,date('t',$baseDate),(1+$thisQuarter)*3,date('Y',$baseDate)));
++$maxVal;
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,1+$thisQuarter*3,date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH :
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0,0,0,date('t',$baseDate),date('m',$baseDate),date('Y',$baseDate)));
++$maxVal;
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK :
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK :
$dayOfWeek = date('w',$baseDate);
$val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate) - $dayOfWeek;
$maxVal = $val + 7;
break;
}
switch ($dynamicRuleType) {
// Adjust Today dates for Yesterday and Tomorrow
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY :
--$maxVal;
--$val;
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW :
++$maxVal;
++$val;
break;
}
// Set the filter column rule attributes ready for writing
$filterColumn->setAttributes(array( 'val' => $val,
'maxVal', $maxVal
)
);
// Set the rules for identifying rows for hide/show
$ruleValues[] = array( 'operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL,
'value' => $val
);
$ruleValues[] = array( 'operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN,
'value' => $maxVal
);
PHPExcel_Calculation_Functions::setReturnDateType($rDateType);
return array(
'method' => '_filterTestInCustomDataSet',
'arguments' => array( 'filterRules' => $ruleValues,
'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND
)
);
}
/**
* Apply the AutoFilter rules to the AutoFilter Range
*
@ -446,7 +562,7 @@ class PHPExcel_Worksheet_AutoFilter
'value' => $ruleValue
);
}
$join = $filterColumn->getAndOr();
$join = $filterColumn->getJoin();
$columnFilterTests[$columnID] = array(
'method' => '_filterTestInCustomDataSet',
'arguments' => array( 'filterRules' => $ruleValues,
@ -456,17 +572,16 @@ class PHPExcel_Worksheet_AutoFilter
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER :
$ruleValues = array();
//var_dump($rules);
foreach($rules as $rule) {
// We should only ever have one Dynamic Filter Rule anyway
$dynamicRuleType = $rule->getGrouping();
echo '$dynamicRuleType is ',$dynamicRuleType,PHP_EOL;
if (($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) ||
($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)) {
// Number based
// Number (Average) based
// Calculate the average
$averageFormula = '=AVERAGE('.$columnID.($rangeStart[1]+1).':'.$columnID.$rangeEnd[1].')';
echo 'Average Formula Result is ',$averageFormula,PHP_EOL;
$average = PHPExcel_Calculation::getInstance()->calculateFormula($averageFormula,NULL,$this->_workSheet->getCell('A1'));
// Set above/below rule based on greaterThan or LessTan
$operator = ($dynamicRuleType === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE)
? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN
: PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN;
@ -476,18 +591,21 @@ echo 'Average Formula Result is ',$averageFormula,PHP_EOL;
$columnFilterTests[$columnID] = array(
'method' => '_filterTestInCustomDataSet',
'arguments' => array( 'filterRules' => $ruleValues,
'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_OR
'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR
)
);
} else {
// Date based
$columnFilterTests[$columnID] = array(
'method' => '_filterTypeDynamicFilters',
'arguments' => $ruleValues
);
if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') {
// Month or Quarter
} else {
// Date Range
$columnFilterTests[$columnID] = $this->_dynamicFilterDateRange($dynamicRuleType, $filterColumn);
break;
}
}
}
break;
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER :
$ruleValues = array();
var_dump($rules);
@ -505,6 +623,7 @@ var_dump($rules);
echo 'Column Filter Test CRITERIA',PHP_EOL;
var_dump($columnFilterTests);
// Execute the column tests for each row in the autoFilter range to determine show/hide,
for ($row = $rangeStart[1]+1; $row <= $rangeEnd[1]; ++$row) {
echo 'Testing Row = ',$row,PHP_EOL;
$result = TRUE;
@ -521,11 +640,12 @@ var_dump($rules);
$columnFilterTest['arguments']
)
);
echo (($result) ? 'VALID' : 'INVALID'),PHP_EOL;
echo (($result) ? 'VALID' : 'INVALID'),PHP_EOL;
// If filter test has resulted in FALSE, exit the loop straightaway rather than running any more tests
if (!$result)
break;
}
// Set show/hide for the row based on the result of the autoFilter result
echo (($result) ? 'SHOW' : 'HIDE'),PHP_EOL;
$this->_workSheet->getRowDimension($row)->setVisible($result);
}

View File

@ -56,12 +56,12 @@ class PHPExcel_Worksheet_AutoFilter_Column
);
/* Multiple Rule Connections */
const AUTOFILTER_COLUMN_ANDOR_AND = 'and';
const AUTOFILTER_COLUMN_ANDOR_OR = 'or';
const AUTOFILTER_COLUMN_JOIN_AND = 'and';
const AUTOFILTER_COLUMN_JOIN_OR = 'or';
private static $_ruleJoin = array(
self::AUTOFILTER_COLUMN_ANDOR_AND,
self::AUTOFILTER_COLUMN_ANDOR_OR,
private static $_ruleJoins = array(
self::AUTOFILTER_COLUMN_JOIN_AND,
self::AUTOFILTER_COLUMN_JOIN_OR,
);
/**
@ -93,7 +93,7 @@ class PHPExcel_Worksheet_AutoFilter_Column
*
* @var string
*/
private $_andOr = self::AUTOFILTER_COLUMN_ANDOR_OR;
private $_join = self::AUTOFILTER_COLUMN_JOIN_OR;
/**
@ -104,6 +104,14 @@ class PHPExcel_Worksheet_AutoFilter_Column
private $_ruleset = array();
/**
* Autofilter Column Dynamic Attributes
*
* @var array of mixed
*/
private $_attributes = array();
/**
* Create a new PHPExcel_Worksheet_AutoFilter_Column
*/
@ -189,33 +197,81 @@ class PHPExcel_Worksheet_AutoFilter_Column
}
/**
* Get AutoFilter Multiple Rules And/Or
* Get AutoFilter Multiple Rules And/Or Join
*
* @return string
*/
public function getAndOr() {
return $this->_andOr;
public function getJoin() {
return $this->_join;
}
/**
* Set AutoFilter Multiple Rules And/Or
*
* @param string $pAndOr And/Or
* @param string $pJoin And/Or
* @throws Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setAndOr($pAndOr = self::AUTOFILTER_COLUMN_ANDOR_OR) {
public function setJoin($pJoin = self::AUTOFILTER_COLUMN_JOIN_OR) {
// Lowercase And/Or
$pAndOr = strtolower($pAndOr);
if (!in_array($pAndOr,self::$_ruleJoin)) {
$pJoin = strtolower($pJoin);
if (!in_array($pJoin,self::$_ruleJoins)) {
throw new PHPExcel_Exception('Invalid rule connection for column AutoFilter.');
}
$this->_andOr = $pAndOr;
$this->_join = $pJoin;
return $this;
}
/**
* Set AutoFilter Attributes
*
* @param string[] $pAttributes
* @throws Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setAttributes($pAttributes = array()) {
$this->_attributes = $pAttributes;
return $this;
}
/**
* Set An AutoFilter Attribute
*
* @param string $pName Attribute Name
* @param string $pValue Attribute Value
* @throws Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setAttribute($pName, $pValue) {
$this->_attributes[$pName] = $pValue;
return $this;
}
/**
* Get AutoFilter Column Attributes
*
* @return string
*/
public function getAttributes() {
return $this->_attributes;
}
/**
* Get specific AutoFilter Column Attribute
*
* @param string $pName Attribute Name
* @return string
*/
public function getAttribute($pName) {
if (isset($this->_attributes[$pName]))
return $this->_attributes[$pName];
return NULL;
}
/**
* Get all AutoFilter Column Rules
*
@ -276,7 +332,7 @@ class PHPExcel_Worksheet_AutoFilter_Column
unset($this->_ruleset[$pIndex]);
// If we've just deleted down to a single rule, then reset And/Or joining to Or
if (count($this->_ruleset) <= 1) {
$this->setAndOr(self::AUTOFILTER_COLUMN_ANDOR_OR);
$this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
}
}
@ -290,7 +346,7 @@ class PHPExcel_Worksheet_AutoFilter_Column
*/
public function clearRules() {
$this->_ruleset = array();
$this->setAndOr(self::AUTOFILTER_COLUMN_ANDOR_OR);
$this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
return $this;
}

View File

@ -197,7 +197,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write
$objWriter->writeAttribute('calcId', '124519');
$objWriter->writeAttribute('calcMode', 'auto');
// fullCalcOnLoad isn't needed if we've recalculating for the save
$objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '0' : '1');
$objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '1' : '0');
$objWriter->endElement();
}

View File

@ -151,7 +151,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ
$autoFilterRange = $pSheet->getAutoFilter()->getRange();
if (!empty($autoFilterRange)) {
$objWriter->writeAttribute('filterMode', 1);
// $pSheet->getAutoFilter()->showHideRows();
$pSheet->getAutoFilter()->showHideRows();
}
// tabColor
@ -760,7 +760,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ
$objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID));
$objWriter->startElement( $column->getFilterType());
if ($column->getAndOr() == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND) {
if ($column->getJoin() == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND) {
$objWriter->writeAttribute('and', 1);
}
@ -772,7 +772,15 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ
$objWriter->writeAttribute('blank', 1);
} elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) {
// Dynamic Filter Rule
$objWriter->writeAttribute('type', $rule->getGrouping());
$objWriter->writeAttribute('type', $rule->getGrouping());
$val = $column->getAttribute('val');
if ($val !== NULL) {
$objWriter->writeAttribute('val', $val);
}
$maxVal = $column->getAttribute('maxVal');
if ($maxVal !== NULL) {
$objWriter->writeAttribute('maxVal', $maxVal);
}
} elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) {
// Top 10 Filter Rule
$objWriter->writeAttribute('val', $rule->getValue());