[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/Worksheet/ -> AutoFilter.php (source)

   1  <?php
   2  
   3  /**
   4   * PHPExcel_Worksheet_AutoFilter
   5   *
   6   * Copyright (c) 2006 - 2015 PHPExcel
   7   *
   8   * This library is free software; you can redistribute it and/or
   9   * modify it under the terms of the GNU Lesser General Public
  10   * License as published by the Free Software Foundation; either
  11   * version 2.1 of the License, or (at your option) any later version.
  12   *
  13   * This library is distributed in the hope that it will be useful,
  14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16   * Lesser General Public License for more details.
  17   *
  18   * You should have received a copy of the GNU Lesser General Public
  19   * License along with this library; if not, write to the Free Software
  20   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  21   *
  22   * @category   PHPExcel
  23   * @package    PHPExcel_Worksheet
  24   * @copyright  Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  25   * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  26   * @version    ##VERSION##, ##DATE##
  27   */
  28  class PHPExcel_Worksheet_AutoFilter
  29  {
  30      /**
  31       * Autofilter Worksheet
  32       *
  33       * @var PHPExcel_Worksheet
  34       */
  35      private $workSheet;
  36  
  37  
  38      /**
  39       * Autofilter Range
  40       *
  41       * @var string
  42       */
  43      private $range = '';
  44  
  45  
  46      /**
  47       * Autofilter Column Ruleset
  48       *
  49       * @var array of PHPExcel_Worksheet_AutoFilter_Column
  50       */
  51      private $columns = array();
  52  
  53  
  54      /**
  55       * Create a new PHPExcel_Worksheet_AutoFilter
  56       *
  57       *    @param    string        $pRange        Cell range (i.e. A1:E10)
  58       * @param PHPExcel_Worksheet $pSheet
  59       */
  60      public function __construct($pRange = '', PHPExcel_Worksheet $pSheet = null)
  61      {
  62          $this->range = $pRange;
  63          $this->workSheet = $pSheet;
  64      }
  65  
  66      /**
  67       * Get AutoFilter Parent Worksheet
  68       *
  69       * @return PHPExcel_Worksheet
  70       */
  71      public function getParent()
  72      {
  73          return $this->workSheet;
  74      }
  75  
  76      /**
  77       * Set AutoFilter Parent Worksheet
  78       *
  79       * @param PHPExcel_Worksheet $pSheet
  80       * @return PHPExcel_Worksheet_AutoFilter
  81       */
  82      public function setParent(PHPExcel_Worksheet $pSheet = null)
  83      {
  84          $this->workSheet = $pSheet;
  85  
  86          return $this;
  87      }
  88  
  89      /**
  90       * Get AutoFilter Range
  91       *
  92       * @return string
  93       */
  94      public function getRange()
  95      {
  96          return $this->range;
  97      }
  98  
  99      /**
 100       *    Set AutoFilter Range
 101       *
 102       *    @param    string        $pRange        Cell range (i.e. A1:E10)
 103       *    @throws    PHPExcel_Exception
 104       *    @return PHPExcel_Worksheet_AutoFilter
 105       */
 106      public function setRange($pRange = '')
 107      {
 108          // Uppercase coordinate
 109          $cellAddress = explode('!', strtoupper($pRange));
 110          if (count($cellAddress) > 1) {
 111              list($worksheet, $pRange) = $cellAddress;
 112          }
 113  
 114          if (strpos($pRange, ':') !== false) {
 115              $this->range = $pRange;
 116          } elseif (empty($pRange)) {
 117              $this->range = '';
 118          } else {
 119              throw new PHPExcel_Exception('Autofilter must be set on a range of cells.');
 120          }
 121  
 122          if (empty($pRange)) {
 123              //    Discard all column rules
 124              $this->columns = array();
 125          } else {
 126              //    Discard any column rules that are no longer valid within this range
 127              list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
 128              foreach ($this->columns as $key => $value) {
 129                  $colIndex = PHPExcel_Cell::columnIndexFromString($key);
 130                  if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) {
 131                      unset($this->columns[$key]);
 132                  }
 133              }
 134          }
 135  
 136          return $this;
 137      }
 138  
 139      /**
 140       * Get all AutoFilter Columns
 141       *
 142       * @throws    PHPExcel_Exception
 143       * @return array of PHPExcel_Worksheet_AutoFilter_Column
 144       */
 145      public function getColumns()
 146      {
 147          return $this->columns;
 148      }
 149  
 150      /**
 151       * Validate that the specified column is in the AutoFilter range
 152       *
 153       * @param    string    $column            Column name (e.g. A)
 154       * @throws    PHPExcel_Exception
 155       * @return    integer    The column offset within the autofilter range
 156       */
 157      public function testColumnInRange($column)
 158      {
 159          if (empty($this->range)) {
 160              throw new PHPExcel_Exception("No autofilter range is defined.");
 161          }
 162  
 163          $columnIndex = PHPExcel_Cell::columnIndexFromString($column);
 164          list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
 165          if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) {
 166              throw new PHPExcel_Exception("Column is outside of current autofilter range.");
 167          }
 168  
 169          return $columnIndex - $rangeStart[0];
 170      }
 171  
 172      /**
 173       * Get a specified AutoFilter Column Offset within the defined AutoFilter range
 174       *
 175       * @param    string    $pColumn        Column name (e.g. A)
 176       * @throws    PHPExcel_Exception
 177       * @return integer    The offset of the specified column within the autofilter range
 178       */
 179      public function getColumnOffset($pColumn)
 180      {
 181          return $this->testColumnInRange($pColumn);
 182      }
 183  
 184      /**
 185       * Get a specified AutoFilter Column
 186       *
 187       * @param    string    $pColumn        Column name (e.g. A)
 188       * @throws    PHPExcel_Exception
 189       * @return PHPExcel_Worksheet_AutoFilter_Column
 190       */
 191      public function getColumn($pColumn)
 192      {
 193          $this->testColumnInRange($pColumn);
 194  
 195          if (!isset($this->columns[$pColumn])) {
 196              $this->columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this);
 197          }
 198  
 199          return $this->columns[$pColumn];
 200      }
 201  
 202      /**
 203       * Get a specified AutoFilter Column by it's offset
 204       *
 205       * @param    integer    $pColumnOffset        Column offset within range (starting from 0)
 206       * @throws    PHPExcel_Exception
 207       * @return PHPExcel_Worksheet_AutoFilter_Column
 208       */
 209      public function getColumnByOffset($pColumnOffset = 0)
 210      {
 211          list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
 212          $pColumn = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $pColumnOffset - 1);
 213  
 214          return $this->getColumn($pColumn);
 215      }
 216  
 217      /**
 218       *    Set AutoFilter
 219       *
 220       *    @param    PHPExcel_Worksheet_AutoFilter_Column|string        $pColumn
 221       *            A simple string containing a Column ID like 'A' is permitted
 222       *    @throws    PHPExcel_Exception
 223       *    @return PHPExcel_Worksheet_AutoFilter
 224       */
 225      public function setColumn($pColumn)
 226      {
 227          if ((is_string($pColumn)) && (!empty($pColumn))) {
 228              $column = $pColumn;
 229          } elseif (is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) {
 230              $column = $pColumn->getColumnIndex();
 231          } else {
 232              throw new PHPExcel_Exception("Column is not within the autofilter range.");
 233          }
 234          $this->testColumnInRange($column);
 235  
 236          if (is_string($pColumn)) {
 237              $this->columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this);
 238          } elseif (is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) {
 239              $pColumn->setParent($this);
 240              $this->columns[$column] = $pColumn;
 241          }
 242          ksort($this->columns);
 243  
 244          return $this;
 245      }
 246  
 247      /**
 248       * Clear a specified AutoFilter Column
 249       *
 250       * @param    string  $pColumn    Column name (e.g. A)
 251       * @throws    PHPExcel_Exception
 252       * @return PHPExcel_Worksheet_AutoFilter
 253       */
 254      public function clearColumn($pColumn)
 255      {
 256          $this->testColumnInRange($pColumn);
 257  
 258          if (isset($this->columns[$pColumn])) {
 259              unset($this->columns[$pColumn]);
 260          }
 261  
 262          return $this;
 263      }
 264  
 265      /**
 266       *    Shift an AutoFilter Column Rule to a different column
 267       *
 268       *    Note: This method bypasses validation of the destination column to ensure it is within this AutoFilter range.
 269       *        Nor does it verify whether any column rule already exists at $toColumn, but will simply overrideany existing value.
 270       *        Use with caution.
 271       *
 272       *    @param    string    $fromColumn        Column name (e.g. A)
 273       *    @param    string    $toColumn        Column name (e.g. B)
 274       *    @return PHPExcel_Worksheet_AutoFilter
 275       */
 276      public function shiftColumn($fromColumn = null, $toColumn = null)
 277      {
 278          $fromColumn = strtoupper($fromColumn);
 279          $toColumn = strtoupper($toColumn);
 280  
 281          if (($fromColumn !== null) && (isset($this->columns[$fromColumn])) && ($toColumn !== null)) {
 282              $this->columns[$fromColumn]->setParent();
 283              $this->columns[$fromColumn]->setColumnIndex($toColumn);
 284              $this->columns[$toColumn] = $this->columns[$fromColumn];
 285              $this->columns[$toColumn]->setParent($this);
 286              unset($this->columns[$fromColumn]);
 287  
 288              ksort($this->columns);
 289          }
 290  
 291          return $this;
 292      }
 293  
 294  
 295      /**
 296       *    Test if cell value is in the defined set of values
 297       *
 298       *    @param    mixed        $cellValue
 299       *    @param    mixed[]        $dataSet
 300       *    @return boolean
 301       */
 302      private static function filterTestInSimpleDataSet($cellValue, $dataSet)
 303      {
 304          $dataSetValues = $dataSet['filterValues'];
 305          $blanks = $dataSet['blanks'];
 306          if (($cellValue == '') || ($cellValue === null)) {
 307              return $blanks;
 308          }
 309          return in_array($cellValue, $dataSetValues);
 310      }
 311  
 312      /**
 313       *    Test if cell value is in the defined set of Excel date values
 314       *
 315       *    @param    mixed        $cellValue
 316       *    @param    mixed[]        $dataSet
 317       *    @return boolean
 318       */
 319      private static function filterTestInDateGroupSet($cellValue, $dataSet)
 320      {
 321          $dateSet = $dataSet['filterValues'];
 322          $blanks = $dataSet['blanks'];
 323          if (($cellValue == '') || ($cellValue === null)) {
 324              return $blanks;
 325          }
 326  
 327          if (is_numeric($cellValue)) {
 328              $dateValue = PHPExcel_Shared_Date::ExcelToPHP($cellValue);
 329              if ($cellValue < 1) {
 330                  //    Just the time part
 331                  $dtVal = date('His', $dateValue);
 332                  $dateSet = $dateSet['time'];
 333              } elseif ($cellValue == floor($cellValue)) {
 334                  //    Just the date part
 335                  $dtVal = date('Ymd', $dateValue);
 336                  $dateSet = $dateSet['date'];
 337              } else {
 338                  //    date and time parts
 339                  $dtVal = date('YmdHis', $dateValue);
 340                  $dateSet = $dateSet['dateTime'];
 341              }
 342              foreach ($dateSet as $dateValue) {
 343                  //    Use of substr to extract value at the appropriate group level
 344                  if (substr($dtVal, 0, strlen($dateValue)) == $dateValue) {
 345                      return true;
 346                  }
 347              }
 348          }
 349          return false;
 350      }
 351  
 352      /**
 353       *    Test if cell value is within a set of values defined by a ruleset
 354       *
 355       *    @param    mixed        $cellValue
 356       *    @param    mixed[]        $ruleSet
 357       *    @return boolean
 358       */
 359      private static function filterTestInCustomDataSet($cellValue, $ruleSet)
 360      {
 361          $dataSet = $ruleSet['filterRules'];
 362          $join = $ruleSet['join'];
 363          $customRuleForBlanks = isset($ruleSet['customRuleForBlanks']) ? $ruleSet['customRuleForBlanks'] : false;
 364  
 365          if (!$customRuleForBlanks) {
 366              //    Blank cells are always ignored, so return a FALSE
 367              if (($cellValue == '') || ($cellValue === null)) {
 368                  return false;
 369              }
 370          }
 371          $returnVal = ($join == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND);
 372          foreach ($dataSet as $rule) {
 373              if (is_numeric($rule['value'])) {
 374                  //    Numeric values are tested using the appropriate operator
 375                  switch ($rule['operator']) {
 376                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
 377                          $retVal    = ($cellValue == $rule['value']);
 378                          break;
 379                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
 380                          $retVal    = ($cellValue != $rule['value']);
 381                          break;
 382                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN:
 383                          $retVal    = ($cellValue > $rule['value']);
 384                          break;
 385                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL:
 386                          $retVal    = ($cellValue >= $rule['value']);
 387                          break;
 388                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN:
 389                          $retVal    = ($cellValue < $rule['value']);
 390                          break;
 391                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL:
 392                          $retVal    = ($cellValue <= $rule['value']);
 393                          break;
 394                  }
 395              } elseif ($rule['value'] == '') {
 396                  switch ($rule['operator']) {
 397                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
 398                          $retVal    = (($cellValue == '') || ($cellValue === null));
 399                          break;
 400                      case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
 401                          $retVal    = (($cellValue != '') && ($cellValue !== null));
 402                          break;
 403                      default:
 404                          $retVal    = true;
 405                          break;
 406                  }
 407              } else {
 408                  //    String values are always tested for equality, factoring in for wildcards (hence a regexp test)
 409                  $retVal    = preg_match('/^'.$rule['value'].'$/i', $cellValue);
 410              }
 411              //    If there are multiple conditions, then we need to test both using the appropriate join operator
 412              switch ($join) {
 413                  case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR:
 414                      $returnVal = $returnVal || $retVal;
 415                      //    Break as soon as we have a TRUE match for OR joins,
 416                      //        to avoid unnecessary additional code execution
 417                      if ($returnVal) {
 418                          return $returnVal;
 419                      }
 420                      break;
 421                  case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND:
 422                      $returnVal = $returnVal && $retVal;
 423                      break;
 424              }
 425          }
 426  
 427          return $returnVal;
 428      }
 429  
 430      /**
 431       *    Test if cell date value is matches a set of values defined by a set of months
 432       *
 433       *    @param    mixed        $cellValue
 434       *    @param    mixed[]        $monthSet
 435       *    @return boolean
 436       */
 437      private static function filterTestInPeriodDateSet($cellValue, $monthSet)
 438      {
 439          //    Blank cells are always ignored, so return a FALSE
 440          if (($cellValue == '') || ($cellValue === null)) {
 441              return false;
 442          }
 443  
 444          if (is_numeric($cellValue)) {
 445              $dateValue = date('m', PHPExcel_Shared_Date::ExcelToPHP($cellValue));
 446              if (in_array($dateValue, $monthSet)) {
 447                  return true;
 448              }
 449          }
 450  
 451          return false;
 452      }
 453  
 454      /**
 455       *    Search/Replace arrays to convert Excel wildcard syntax to a regexp syntax for preg_matching
 456       *
 457       *    @var    array
 458       */
 459      private static $fromReplace = array('\*', '\?', '~~', '~.*', '~.?');
 460      private static $toReplace   = array('.*', '.',  '~',  '\*',  '\?');
 461  
 462  
 463      /**
 464       *    Convert a dynamic rule daterange to a custom filter range expression for ease of calculation
 465       *
 466       *    @param    string                                        $dynamicRuleType
 467       *    @param    PHPExcel_Worksheet_AutoFilter_Column        &$filterColumn
 468       *    @return mixed[]
 469       */
 470      private function dynamicFilterDateRange($dynamicRuleType, &$filterColumn)
 471      {
 472          $rDateType = PHPExcel_Calculation_Functions::getReturnDateType();
 473          PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC);
 474          $val = $maxVal = null;
 475  
 476          $ruleValues = array();
 477          $baseDate = PHPExcel_Calculation_DateTime::DATENOW();
 478          //    Calculate start/end dates for the required date range based on current date
 479          switch ($dynamicRuleType) {
 480              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK:
 481                  $baseDate = strtotime('-7 days', $baseDate);
 482                  break;
 483              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK:
 484                  $baseDate = strtotime('-7 days', $baseDate);
 485                  break;
 486              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH:
 487                  $baseDate = strtotime('-1 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 488                  break;
 489              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH:
 490                  $baseDate = strtotime('+1 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 491                  break;
 492              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER:
 493                  $baseDate = strtotime('-3 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 494                  break;
 495              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER:
 496                  $baseDate = strtotime('+3 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 497                  break;
 498              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR:
 499                  $baseDate = strtotime('-1 year', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 500                  break;
 501              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR:
 502                  $baseDate = strtotime('+1 year', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 503                  break;
 504          }
 505  
 506          switch ($dynamicRuleType) {
 507              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY:
 508              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY:
 509              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW:
 510                  $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day', $baseDate));
 511                  $val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate);
 512                  break;
 513              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE:
 514                  $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day', $baseDate));
 515                  $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1, date('Y', $baseDate)));
 516                  break;
 517              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR:
 518              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR:
 519              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR:
 520                  $maxVal = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 31, 12, date('Y', $baseDate)));
 521                  ++$maxVal;
 522                  $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1, date('Y', $baseDate)));
 523                  break;
 524              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER:
 525              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER:
 526              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER:
 527                  $thisMonth = date('m', $baseDate);
 528                  $thisQuarter = floor(--$thisMonth / 3);
 529                  $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0, 0, 0, date('t', $baseDate), (1+$thisQuarter)*3, date('Y', $baseDate)));
 530                  ++$maxVal;
 531                  $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1+$thisQuarter*3, date('Y', $baseDate)));
 532                  break;
 533              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH:
 534              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH:
 535              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH:
 536                  $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0, 0, 0, date('t', $baseDate), date('m', $baseDate), date('Y', $baseDate)));
 537                  ++$maxVal;
 538                  $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
 539                  break;
 540              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK:
 541              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK:
 542              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK:
 543                  $dayOfWeek = date('w', $baseDate);
 544                  $val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate) - $dayOfWeek;
 545                  $maxVal = $val + 7;
 546                  break;
 547          }
 548  
 549          switch ($dynamicRuleType) {
 550              //    Adjust Today dates for Yesterday and Tomorrow
 551              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY:
 552                  --$maxVal;
 553                  --$val;
 554                  break;
 555              case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW:
 556                  ++$maxVal;
 557                  ++$val;
 558                  break;
 559          }
 560  
 561          //    Set the filter column rule attributes ready for writing
 562          $filterColumn->setAttributes(array('val' => $val, 'maxVal' => $maxVal));
 563  
 564          //    Set the rules for identifying rows for hide/show
 565          $ruleValues[] = array('operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 'value' => $val);
 566          $ruleValues[] = array('operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, 'value' => $maxVal);
 567          PHPExcel_Calculation_Functions::setReturnDateType($rDateType);
 568  
 569          return array('method' => 'filterTestInCustomDataSet', 'arguments' => array('filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND));
 570      }
 571  
 572      private function calculateTopTenValue($columnID, $startRow, $endRow, $ruleType, $ruleValue)
 573      {
 574          $range = $columnID.$startRow.':'.$columnID.$endRow;
 575          $dataValues = PHPExcel_Calculation_Functions::flattenArray($this->workSheet->rangeToArray($range, null, true, false));
 576  
 577          $dataValues = array_filter($dataValues);
 578          if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) {
 579              rsort($dataValues);
 580          } else {
 581              sort($dataValues);
 582          }
 583  
 584          return array_pop(array_slice($dataValues, 0, $ruleValue));
 585      }
 586  
 587      /**
 588       *    Apply the AutoFilter rules to the AutoFilter Range
 589       *
 590       *    @throws    PHPExcel_Exception
 591       *    @return PHPExcel_Worksheet_AutoFilter
 592       */
 593      public function showHideRows()
 594      {
 595          list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
 596  
 597          //    The heading row should always be visible
 598  //        echo 'AutoFilter Heading Row ', $rangeStart[1],' is always SHOWN',PHP_EOL;
 599          $this->workSheet->getRowDimension($rangeStart[1])->setVisible(true);
 600  
 601          $columnFilterTests = array();
 602          foreach ($this->columns as $columnID => $filterColumn) {
 603              $rules = $filterColumn->getRules();
 604              switch ($filterColumn->getFilterType()) {
 605                  case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER:
 606                      $ruleValues = array();
 607                      //    Build a list of the filter value selections
 608                      foreach ($rules as $rule) {
 609                          $ruleType = $rule->getRuleType();
 610                          $ruleValues[] = $rule->getValue();
 611                      }
 612                      //    Test if we want to include blanks in our filter criteria
 613                      $blanks = false;
 614                      $ruleDataSet = array_filter($ruleValues);
 615                      if (count($ruleValues) != count($ruleDataSet)) {
 616                          $blanks = true;
 617                      }
 618                      if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER) {
 619                          //    Filter on absolute values
 620                          $columnFilterTests[$columnID] = array(
 621                              'method' => 'filterTestInSimpleDataSet',
 622                              'arguments' => array('filterValues' => $ruleDataSet, 'blanks' => $blanks)
 623                          );
 624                      } else {
 625                          //    Filter on date group values
 626                          $arguments = array(
 627                              'date' => array(),
 628                              'time' => array(),
 629                              'dateTime' => array(),
 630                          );
 631                          foreach ($ruleDataSet as $ruleValue) {
 632                              $date = $time = '';
 633                              if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) &&
 634                                  ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')) {
 635                                  $date .= sprintf('%04d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]);
 636                              }
 637                              if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) &&
 638                                  ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')) {
 639                                  $date .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]);
 640                              }
 641                              if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) &&
 642                                  ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')) {
 643                                  $date .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]);
 644                              }
 645                              if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) &&
 646                                  ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')) {
 647                                  $time .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]);
 648                              }
 649                              if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) &&
 650                                  ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')) {
 651                                  $time .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]);
 652                              }
 653                              if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) &&
 654                                  ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')) {
 655                                  $time .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]);
 656                              }
 657                              $dateTime = $date . $time;
 658                              $arguments['date'][] = $date;
 659                              $arguments['time'][] = $time;
 660                              $arguments['dateTime'][] = $dateTime;
 661                          }
 662                          //    Remove empty elements
 663                          $arguments['date'] = array_filter($arguments['date']);
 664                          $arguments['time'] = array_filter($arguments['time']);
 665                          $arguments['dateTime'] = array_filter($arguments['dateTime']);
 666                          $columnFilterTests[$columnID] = array(
 667                              'method' => 'filterTestInDateGroupSet',
 668                              'arguments' => array('filterValues' => $arguments, 'blanks' => $blanks)
 669                          );
 670                      }
 671                      break;
 672                  case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER:
 673                      $customRuleForBlanks = false;
 674                      $ruleValues = array();
 675                      //    Build a list of the filter value selections
 676                      foreach ($rules as $rule) {
 677                          $ruleType = $rule->getRuleType();
 678                          $ruleValue = $rule->getValue();
 679                          if (!is_numeric($ruleValue)) {
 680                              //    Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards
 681                              $ruleValue = preg_quote($ruleValue);
 682                              $ruleValue = str_replace(self::$fromReplace, self::$toReplace, $ruleValue);
 683                              if (trim($ruleValue) == '') {
 684                                  $customRuleForBlanks = true;
 685                                  $ruleValue = trim($ruleValue);
 686                              }
 687                          }
 688                          $ruleValues[] = array('operator' => $rule->getOperator(), 'value' => $ruleValue);
 689                      }
 690                      $join = $filterColumn->getJoin();
 691                      $columnFilterTests[$columnID] = array(
 692                          'method' => 'filterTestInCustomDataSet',
 693                          'arguments' => array('filterRules' => $ruleValues, 'join' => $join, 'customRuleForBlanks' => $customRuleForBlanks)
 694                      );
 695                      break;
 696                  case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER:
 697                      $ruleValues = array();
 698                      foreach ($rules as $rule) {
 699                          //    We should only ever have one Dynamic Filter Rule anyway
 700                          $dynamicRuleType = $rule->getGrouping();
 701                          if (($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) ||
 702                              ($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)) {
 703                              //    Number (Average) based
 704                              //    Calculate the average
 705                              $averageFormula = '=AVERAGE('.$columnID.($rangeStart[1]+1).':'.$columnID.$rangeEnd[1].')';
 706                              $average = PHPExcel_Calculation::getInstance()->calculateFormula($averageFormula, null, $this->workSheet->getCell('A1'));
 707                              //    Set above/below rule based on greaterThan or LessTan
 708                              $operator = ($dynamicRuleType === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE)
 709                                  ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN
 710                                  : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN;
 711                              $ruleValues[] = array('operator' => $operator,
 712                                                     'value' => $average
 713                                                   );
 714                              $columnFilterTests[$columnID] = array(
 715                                  'method' => 'filterTestInCustomDataSet',
 716                                  'arguments' => array('filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR)
 717                              );
 718                          } else {
 719                              //    Date based
 720                              if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') {
 721                                  //    Month or Quarter
 722                                  sscanf($dynamicRuleType, '%[A-Z]%d', $periodType, $period);
 723                                  if ($periodType == 'M') {
 724                                      $ruleValues = array($period);
 725                                  } else {
 726                                      --$period;
 727                                      $periodEnd = (1+$period)*3;
 728                                      $periodStart = 1+$period*3;
 729                                      $ruleValues = range($periodStart, $periodEnd);
 730                                  }
 731                                  $columnFilterTests[$columnID] = array(
 732                                      'method' => 'filterTestInPeriodDateSet',
 733                                      'arguments' => $ruleValues
 734                                  );
 735                                  $filterColumn->setAttributes(array());
 736                              } else {
 737                                  //    Date Range
 738                                  $columnFilterTests[$columnID] = $this->dynamicFilterDateRange($dynamicRuleType, $filterColumn);
 739                                  break;
 740                              }
 741                          }
 742                      }
 743                      break;
 744                  case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER:
 745                      $ruleValues = array();
 746                      $dataRowCount = $rangeEnd[1] - $rangeStart[1];
 747                      foreach ($rules as $rule) {
 748                          //    We should only ever have one Dynamic Filter Rule anyway
 749                          $toptenRuleType = $rule->getGrouping();
 750                          $ruleValue = $rule->getValue();
 751                          $ruleOperator = $rule->getOperator();
 752                      }
 753                      if ($ruleOperator === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) {
 754                          $ruleValue = floor($ruleValue * ($dataRowCount / 100));
 755                      }
 756                      if ($ruleValue < 1) {
 757                          $ruleValue = 1;
 758                      }
 759                      if ($ruleValue > 500) {
 760                          $ruleValue = 500;
 761                      }
 762  
 763                      $maxVal = $this->calculateTopTenValue($columnID, $rangeStart[1]+1, $rangeEnd[1], $toptenRuleType, $ruleValue);
 764  
 765                      $operator = ($toptenRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP)
 766                          ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL
 767                          : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL;
 768                      $ruleValues[] = array('operator' => $operator, 'value' => $maxVal);
 769                      $columnFilterTests[$columnID] = array(
 770                          'method' => 'filterTestInCustomDataSet',
 771                          'arguments' => array('filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR)
 772                      );
 773                      $filterColumn->setAttributes(array('maxVal' => $maxVal));
 774                      break;
 775              }
 776          }
 777  
 778  //        echo 'Column Filter Test CRITERIA',PHP_EOL;
 779  //        var_dump($columnFilterTests);
 780  //
 781          //    Execute the column tests for each row in the autoFilter range to determine show/hide,
 782          for ($row = $rangeStart[1]+1; $row <= $rangeEnd[1]; ++$row) {
 783  //            echo 'Testing Row = ', $row,PHP_EOL;
 784              $result = true;
 785              foreach ($columnFilterTests as $columnID => $columnFilterTest) {
 786  //                echo 'Testing cell ', $columnID.$row,PHP_EOL;
 787                  $cellValue = $this->workSheet->getCell($columnID.$row)->getCalculatedValue();
 788  //                echo 'Value is ', $cellValue,PHP_EOL;
 789                  //    Execute the filter test
 790                  $result = $result &&
 791                      call_user_func_array(
 792                          array('PHPExcel_Worksheet_AutoFilter', $columnFilterTest['method']),
 793                          array($cellValue, $columnFilterTest['arguments'])
 794                      );
 795  //                echo (($result) ? 'VALID' : 'INVALID'),PHP_EOL;
 796                  //    If filter test has resulted in FALSE, exit the loop straightaway rather than running any more tests
 797                  if (!$result) {
 798                      break;
 799                  }
 800              }
 801              //    Set show/hide for the row based on the result of the autoFilter result
 802  //            echo (($result) ? 'SHOW' : 'HIDE'),PHP_EOL;
 803              $this->workSheet->getRowDimension($row)->setVisible($result);
 804          }
 805  
 806          return $this;
 807      }
 808  
 809  
 810      /**
 811       * Implement PHP __clone to create a deep clone, not just a shallow copy.
 812       */
 813      public function __clone()
 814      {
 815          $vars = get_object_vars($this);
 816          foreach ($vars as $key => $value) {
 817              if (is_object($value)) {
 818                  if ($key == 'workSheet') {
 819                      //    Detach from worksheet
 820                      $this->{$key} = null;
 821                  } else {
 822                      $this->{$key} = clone $value;
 823                  }
 824              } elseif ((is_array($value)) && ($key == 'columns')) {
 825                  //    The columns array of PHPExcel_Worksheet_AutoFilter objects
 826                  $this->{$key} = array();
 827                  foreach ($value as $k => $v) {
 828                      $this->{$key}[$k] = clone $v;
 829                      // attach the new cloned Column to this new cloned Autofilter object
 830                      $this->{$key}[$k]->setParent($this);
 831                  }
 832              } else {
 833                  $this->{$key} = $value;
 834              }
 835          }
 836      }
 837  
 838      /**
 839       * toString method replicates previous behavior by returning the range if object is
 840       *    referenced as a property of its parent.
 841       */
 842      public function __toString()
 843      {
 844          return (string) $this->range;
 845      }
 846  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1