_range = $pRange; $this->_workSheet = $pSheet; } /** * Get AutoFilter Parent Worksheet * * @return PHPExcel_Worksheet */ public function getParent() { return $this->_workSheet; } /** * Set AutoFilter Parent Worksheet * * @param PHPExcel_Worksheet $pSheet * @return PHPExcel_Worksheet_AutoFilter */ public function setParent(PHPExcel_Worksheet $pSheet = NULL) { $this->_workSheet = $pSheet; return $this; } /** * Get AutoFilter Range * * @return string */ public function getRange() { return $this->_range; } /** * Set AutoFilter Range * * @param string $pRange Cell range (i.e. A1:E10) * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter */ public function setRange($pRange = '') { // Uppercase coordinate $cellAddress = explode('!',strtoupper($pRange)); if (count($cellAddress) > 1) { list($worksheet,$pRange) = $cellAddress; } if (strpos($pRange,':') !== FALSE) { $this->_range = $pRange; } elseif(empty($pRange)) { $this->_range = ''; } else { throw new PHPExcel_Exception('Autofilter must be set on a range of cells.'); } if (empty($pRange)) { // Discard all column rules $this->_columns = array(); } else { // Discard any column rules that are no longer valid within this range list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); foreach($this->_columns as $key => $value) { $colIndex = PHPExcel_Cell::columnIndexFromString($key); if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) { unset($this->_columns[$key]); } } } return $this; } /** * Get all AutoFilter Columns * * @throws PHPExcel_Exception * @return array of PHPExcel_Worksheet_AutoFilter_Column */ public function getColumns() { return $this->_columns; } /** * Validate that the specified column is in the AutoFilter range * * @param string $column Column name (e.g. A) * @throws PHPExcel_Exception * @return integer The column offset within the autofilter range */ public function testColumnInRange($column) { if (empty($this->_range)) { throw new PHPExcel_Exception("No autofilter range is defined."); } $columnIndex = PHPExcel_Cell::columnIndexFromString($column); list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) { throw new PHPExcel_Exception("Column is outside of current autofilter range."); } return $columnIndex - $rangeStart[0]; } /** * Get a specified AutoFilter Column Offset within the defined AutoFilter range * * @param string $pColumn Column name (e.g. A) * @throws PHPExcel_Exception * @return integer The offset of the specified column within the autofilter range */ public function getColumnOffset($pColumn) { return $this->testColumnInRange($pColumn); } /** * Get a specified AutoFilter Column * * @param string $pColumn Column name (e.g. A) * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function getColumn($pColumn) { $this->testColumnInRange($pColumn); if (!isset($this->_columns[$pColumn])) { $this->_columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this); } return $this->_columns[$pColumn]; } /** * Get a specified AutoFilter Column by it's offset * * @param integer $pColumnOffset Column offset within range (starting from 0) * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function getColumnByOffset($pColumnOffset = 0) { list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); $pColumn = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $pColumnOffset - 1); return $this->getColumn($pColumn); } /** * Set AutoFilter * * @param PHPExcel_Worksheet_AutoFilter_Column|string $pColumn * A simple string containing a Column ID like 'A' is permitted * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter */ public function setColumn($pColumn) { if ((is_string($pColumn)) && (!empty($pColumn))) { $column = $pColumn; } elseif(is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) { $column = $pColumn->getColumnIndex(); } else { throw new PHPExcel_Exception("Column is not within the autofilter range."); } $this->testColumnInRange($column); if (is_string($pColumn)) { $this->_columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this); } elseif(is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) { $pColumn->setParent($this); $this->_columns[$column] = $pColumn; } ksort($this->_columns); return $this; } /** * Clear a specified AutoFilter Column * * @param string $pColumn Column name (e.g. A) * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter */ public function clearColumn($pColumn) { $this->testColumnInRange($pColumn); if (isset($this->_columns[$pColumn])) { unset($this->_columns[$pColumn]); } return $this; } /** * Shift an AutoFilter Column Rule to a different column * * Note: This method bypasses validation of the destination column to ensure it is within this AutoFilter range. * Nor does it verify whether any column rule already exists at $toColumn, but will simply overrideany existing value. * Use with caution. * * @param string $fromColumn Column name (e.g. A) * @param string $toColumn Column name (e.g. B) * @return PHPExcel_Worksheet_AutoFilter */ public function shiftColumn($fromColumn=NULL,$toColumn=NULL) { $fromColumn = strtoupper($fromColumn); $toColumn = strtoupper($toColumn); if (($fromColumn !== NULL) && (isset($this->_columns[$fromColumn])) && ($toColumn !== NULL)) { $this->_columns[$fromColumn]->setParent(); $this->_columns[$fromColumn]->setColumnIndex($toColumn); $this->_columns[$toColumn] = $this->_columns[$fromColumn]; $this->_columns[$toColumn]->setParent($this); unset($this->_columns[$fromColumn]); ksort($this->_columns); } return $this; } /** * Test if cell value is in the defined set of values * * @param mixed $cellValue * @param mixed[] $dataSet * @return boolean */ private static function _filterTestInSimpleDataSet($cellValue,$dataSet) { $dataSetValues = $dataSet['filterValues']; $blanks = $dataSet['blanks']; if (($cellValue == '') || ($cellValue === NULL)) { return $blanks; } return in_array($cellValue,$dataSetValues); } /** * Test if cell value is in the defined set of Excel date values * * @param mixed $cellValue * @param mixed[] $dataSet * @return boolean */ private static function _filterTestInDateGroupSet($cellValue,$dataSet) { $dateSet = $dataSet['filterValues']; $blanks = $dataSet['blanks']; if (($cellValue == '') || ($cellValue === NULL)) { return $blanks; } if (is_numeric($cellValue)) { $dateValue = PHPExcel_Shared_Date::ExcelToPHP($cellValue); if ($cellValue < 1) { // Just the time part $dtVal = date('His',$dateValue); $dateSet = $dateSet['time']; } elseif($cellValue == floor($cellValue)) { // Just the date part $dtVal = date('Ymd',$dateValue); $dateSet = $dateSet['date']; } else { // date and time parts $dtVal = date('YmdHis',$dateValue); $dateSet = $dateSet['dateTime']; } foreach($dateSet as $dateValue) { // Use of substr to extract value at the appropriate group level if (substr($dtVal,0,strlen($dateValue)) == $dateValue) return TRUE; } } return FALSE; } /** * Test if cell value is within a set of values defined by a ruleset * * @param mixed $cellValue * @param mixed[] $ruleSet * @return boolean */ private static function _filterTestInCustomDataSet($cellValue, $ruleSet) { $dataSet = $ruleSet['filterRules']; $join = $ruleSet['join']; $customRuleForBlanks = isset($ruleSet['customRuleForBlanks']) ? $ruleSet['customRuleForBlanks'] : FALSE; if (!$customRuleForBlanks) { // Blank cells are always ignored, so return a FALSE if (($cellValue == '') || ($cellValue === NULL)) { return FALSE; } } $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 switch ($rule['operator']) { case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL : $retVal = ($cellValue == $rule['value']); break; case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL : $retVal = ($cellValue != $rule['value']); break; case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN : $retVal = ($cellValue > $rule['value']); break; case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL : $retVal = ($cellValue >= $rule['value']); break; case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN : $retVal = ($cellValue < $rule['value']); break; case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL : $retVal = ($cellValue <= $rule['value']); break; } } elseif($rule['value'] == '') { switch ($rule['operator']) { case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL : $retVal = (($cellValue == '') || ($cellValue === NULL)); break; case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL : $retVal = (($cellValue != '') && ($cellValue !== NULL)); break; default : $retVal = TRUE; break; } } else { // String values are always tested for equality, factoring in for wildcards (hence a regexp test) $retVal = preg_match('/^'.$rule['value'].'$/i',$cellValue); } // 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_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_JOIN_AND : $returnVal = $returnVal && $retVal; break; } } return $returnVal; } /** * Test if cell date value is matches a set of values defined by a set of months * * @param mixed $cellValue * @param mixed[] $monthSet * @return boolean */ private static function _filterTestInPeriodDateSet($cellValue, $monthSet) { // Blank cells are always ignored, so return a FALSE if (($cellValue == '') || ($cellValue === NULL)) { return FALSE; } if (is_numeric($cellValue)) { $dateValue = date('m',PHPExcel_Shared_Date::ExcelToPHP($cellValue)); if (in_array($dateValue,$monthSet)) { return TRUE; } } return FALSE; } /** * Search/Replace arrays to convert Excel wildcard syntax to a regexp syntax for preg_matching * * @var array */ private static $_fromReplace = array('\*', '\?', '~~', '~.*', '~.?'); private static $_toReplace = array('.*', '.', '~', '\*', '\?'); /** * Convert a dynamic rule daterange to a custom filter range expression for ease of calculation * * @param string $dynamicRuleType * @param PHPExcel_Worksheet_AutoFilter_Column &$filterColumn * @return mixed[] */ 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(); // Calculate start/end dates for the required date range based on current date 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 ) ); } private function _calculateTopTenValue($columnID,$startRow,$endRow,$ruleType,$ruleValue) { $range = $columnID.$startRow.':'.$columnID.$endRow; $dataValues = PHPExcel_Calculation_Functions::flattenArray( $this->_workSheet->rangeToArray($range,NULL,TRUE,FALSE) ); $dataValues = array_filter($dataValues); if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) { rsort($dataValues); } else { sort($dataValues); } return array_pop(array_slice($dataValues,0,$ruleValue)); } /** * Apply the AutoFilter rules to the AutoFilter Range * * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter */ public function showHideRows() { list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); // The heading row should always be visible // echo 'AutoFilter Heading Row ',$rangeStart[1],' is always SHOWN',PHP_EOL; $this->_workSheet->getRowDimension($rangeStart[1])->setVisible(TRUE); $columnFilterTests = array(); foreach($this->_columns as $columnID => $filterColumn) { $rules = $filterColumn->getRules(); switch ($filterColumn->getFilterType()) { case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER : $ruleValues = array(); // Build a list of the filter value selections foreach($rules as $rule) { $ruleType = $rule->getRuleType(); $ruleValues[] = $rule->getValue(); } // Test if we want to include blanks in our filter criteria $blanks = FALSE; $ruleDataSet = array_filter($ruleValues); if (count($ruleValues) != count($ruleDataSet)) $blanks = TRUE; if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER) { // Filter on absolute values $columnFilterTests[$columnID] = array( 'method' => '_filterTestInSimpleDataSet', 'arguments' => array( 'filterValues' => $ruleDataSet, 'blanks' => $blanks ) ); } else { // Filter on date group values $arguments = array( 'date' => array(), 'time' => array(), 'dateTime' => array(), ); foreach($ruleDataSet as $ruleValue) { $date = $time = ''; if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) && ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')) $date .= sprintf('%04d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]); if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) && ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')) $date .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]); if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) && ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')) $date .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]); if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) && ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')) $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]); if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) && ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')) $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]); if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) && ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')) $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]); $dateTime = $date . $time; $arguments['date'][] = $date; $arguments['time'][] = $time; $arguments['dateTime'][] = $dateTime; } // Remove empty elements $arguments['date'] = array_filter($arguments['date']); $arguments['time'] = array_filter($arguments['time']); $arguments['dateTime'] = array_filter($arguments['dateTime']); $columnFilterTests[$columnID] = array( 'method' => '_filterTestInDateGroupSet', 'arguments' => array( 'filterValues' => $arguments, 'blanks' => $blanks ) ); } break; case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER : $customRuleForBlanks = FALSE; $ruleValues = array(); // Build a list of the filter value selections foreach($rules as $rule) { $ruleType = $rule->getRuleType(); $ruleValue = $rule->getValue(); if (!is_numeric($ruleValue)) { // Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards $ruleValue = preg_quote($ruleValue); $ruleValue = str_replace(self::$_fromReplace,self::$_toReplace,$ruleValue); if (trim($ruleValue) == '') { $customRuleForBlanks = TRUE; $ruleValue = trim($ruleValue); } } $ruleValues[] = array( 'operator' => $rule->getOperator(), 'value' => $ruleValue ); } $join = $filterColumn->getJoin(); $columnFilterTests[$columnID] = array( 'method' => '_filterTestInCustomDataSet', 'arguments' => array( 'filterRules' => $ruleValues, 'join' => $join, 'customRuleForBlanks' => $customRuleForBlanks ) ); break; case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER : $ruleValues = array(); foreach($rules as $rule) { // We should only ever have one Dynamic Filter Rule anyway $dynamicRuleType = $rule->getGrouping(); if (($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) || ($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)) { // Number (Average) based // Calculate the average $averageFormula = '=AVERAGE('.$columnID.($rangeStart[1]+1).':'.$columnID.$rangeEnd[1].')'; $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; $ruleValues[] = array( 'operator' => $operator, 'value' => $average ); $columnFilterTests[$columnID] = array( 'method' => '_filterTestInCustomDataSet', 'arguments' => array( 'filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR ) ); } else { // Date based if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') { // Month or Quarter sscanf($dynamicRuleType,'%[A-Z]%d', $periodType, $period); if ($periodType == 'M') { $ruleValues = array($period); } else { --$period; $periodEnd = (1+$period)*3; $periodStart = 1+$period*3; $ruleValues = range($periodStart,periodEnd); } $columnFilterTests[$columnID] = array( 'method' => '_filterTestInPeriodDateSet', 'arguments' => $ruleValues ); $filterColumn->setAttributes(array()); } else { // Date Range $columnFilterTests[$columnID] = $this->_dynamicFilterDateRange($dynamicRuleType, $filterColumn); break; } } } break; case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER : $ruleValues = array(); $dataRowCount = $rangeEnd[1] - $rangeStart[1]; foreach($rules as $rule) { // We should only ever have one Dynamic Filter Rule anyway $toptenRuleType = $rule->getGrouping(); $ruleValue = $rule->getValue(); $ruleOperator = $rule->getOperator(); } if ($ruleOperator === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) { $ruleValue = floor($ruleValue * ($dataRowCount / 100)); } if ($ruleValue < 1) $ruleValue = 1; if ($ruleValue > 500) $ruleValue = 500; $maxVal = $this->_calculateTopTenValue($columnID,$rangeStart[1]+1,$rangeEnd[1],$toptenRuleType,$ruleValue); $operator = ($toptenRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL; $ruleValues[] = array( 'operator' => $operator, 'value' => $maxVal ); $columnFilterTests[$columnID] = array( 'method' => '_filterTestInCustomDataSet', 'arguments' => array( 'filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR ) ); $filterColumn->setAttributes( array('maxVal' => $maxVal) ); break; } } // 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; foreach($columnFilterTests as $columnID => $columnFilterTest) { // echo 'Testing cell ',$columnID.$row,PHP_EOL; $cellValue = $this->_workSheet->getCell($columnID.$row)->getCalculatedValue(); // echo 'Value is ',$cellValue,PHP_EOL; // Execute the filter test $result = $result && call_user_func_array( array('PHPExcel_Worksheet_AutoFilter',$columnFilterTest['method']), array( $cellValue, $columnFilterTest['arguments'] ) ); // 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); } return $this; } /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ public function __clone() { $vars = get_object_vars($this); foreach ($vars as $key => $value) { if (is_object($value)) { if ($key == '_workSheet') { // Detach from worksheet $this->{$key} = NULL; } else { $this->{$key} = clone $value; } } elseif ((is_array($value)) && ($key == '_columns')) { // The columns array of PHPExcel_Worksheet_AutoFilter objects $this->{$key} = array(); foreach ($value as $k => $v) { $this->{$key}[$k] = clone $v; // attach the new cloned Column to this new cloned Autofilter object $this->{$key}[$k]->setParent($this); } } else { $this->{$key} = $value; } } } /** * toString method replicates previous behavior by returning the range if object is * referenced as a property of its parent. */ public function __toString() { return (string) $this->_range; } }