[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/ -> Cell.php (source)

   1  <?php
   2  
   3  /**
   4   *    PHPExcel_Cell
   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_Cell
  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_Cell
  29  {
  30      /**
  31       *  Default range variable constant
  32       *
  33       *  @var  string
  34       */
  35      const DEFAULT_RANGE = 'A1:A1';
  36  
  37      /**
  38       *    Value binder to use
  39       *
  40       *    @var    PHPExcel_Cell_IValueBinder
  41       */
  42      private static $valueBinder;
  43  
  44      /**
  45       *    Value of the cell
  46       *
  47       *    @var    mixed
  48       */
  49      private $value;
  50  
  51      /**
  52       *    Calculated value of the cell (used for caching)
  53       *    This returns the value last calculated by MS Excel or whichever spreadsheet program was used to
  54       *        create the original spreadsheet file.
  55       *    Note that this value is not guaranteed to reflect the actual calculated value because it is
  56       *        possible that auto-calculation was disabled in the original spreadsheet, and underlying data
  57       *        values used by the formula have changed since it was last calculated.
  58       *
  59       *    @var mixed
  60       */
  61      private $calculatedValue;
  62  
  63      /**
  64       *    Type of the cell data
  65       *
  66       *    @var    string
  67       */
  68      private $dataType;
  69  
  70      /**
  71       *    Parent worksheet
  72       *
  73       *    @var    PHPExcel_CachedObjectStorage_CacheBase
  74       */
  75      private $parent;
  76  
  77      /**
  78       *    Index to cellXf
  79       *
  80       *    @var    int
  81       */
  82      private $xfIndex = 0;
  83  
  84      /**
  85       *    Attributes of the formula
  86       *
  87       */
  88      private $formulaAttributes;
  89  
  90  
  91      /**
  92       *    Send notification to the cache controller
  93       *
  94       *    @return void
  95       **/
  96      public function notifyCacheController()
  97      {
  98          $this->parent->updateCacheData($this);
  99  
 100          return $this;
 101      }
 102  
 103      public function detach()
 104      {
 105          $this->parent = null;
 106      }
 107  
 108      public function attach(PHPExcel_CachedObjectStorage_CacheBase $parent)
 109      {
 110          $this->parent = $parent;
 111      }
 112  
 113  
 114      /**
 115       *    Create a new Cell
 116       *
 117       *    @param    mixed                $pValue
 118       *    @param    string                $pDataType
 119       *    @param    PHPExcel_Worksheet    $pSheet
 120       *    @throws    PHPExcel_Exception
 121       */
 122      public function __construct($pValue = null, $pDataType = null, PHPExcel_Worksheet $pSheet = null)
 123      {
 124          // Initialise cell value
 125          $this->value = $pValue;
 126  
 127          // Set worksheet cache
 128          $this->parent = $pSheet->getCellCacheController();
 129  
 130          // Set datatype?
 131          if ($pDataType !== null) {
 132              if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2) {
 133                  $pDataType = PHPExcel_Cell_DataType::TYPE_STRING;
 134              }
 135              $this->dataType = $pDataType;
 136          } elseif (!self::getValueBinder()->bindValue($this, $pValue)) {
 137              throw new PHPExcel_Exception("Value could not be bound to cell.");
 138          }
 139      }
 140  
 141      /**
 142       *    Get cell coordinate column
 143       *
 144       *    @return    string
 145       */
 146      public function getColumn()
 147      {
 148          return $this->parent->getCurrentColumn();
 149      }
 150  
 151      /**
 152       *    Get cell coordinate row
 153       *
 154       *    @return    int
 155       */
 156      public function getRow()
 157      {
 158          return $this->parent->getCurrentRow();
 159      }
 160  
 161      /**
 162       *    Get cell coordinate
 163       *
 164       *    @return    string
 165       */
 166      public function getCoordinate()
 167      {
 168          return $this->parent->getCurrentAddress();
 169      }
 170  
 171      /**
 172       *    Get cell value
 173       *
 174       *    @return    mixed
 175       */
 176      public function getValue()
 177      {
 178          return $this->value;
 179      }
 180  
 181      /**
 182       *    Get cell value with formatting
 183       *
 184       *    @return    string
 185       */
 186      public function getFormattedValue()
 187      {
 188          return (string) PHPExcel_Style_NumberFormat::toFormattedString(
 189              $this->getCalculatedValue(),
 190              $this->getStyle()
 191                  ->getNumberFormat()->getFormatCode()
 192          );
 193      }
 194  
 195      /**
 196       *    Set cell value
 197       *
 198       *    Sets the value for a cell, automatically determining the datatype using the value binder
 199       *
 200       *    @param    mixed    $pValue                    Value
 201       *    @return    PHPExcel_Cell
 202       *    @throws    PHPExcel_Exception
 203       */
 204      public function setValue($pValue = null)
 205      {
 206          if (!self::getValueBinder()->bindValue($this, $pValue)) {
 207              throw new PHPExcel_Exception("Value could not be bound to cell.");
 208          }
 209          return $this;
 210      }
 211  
 212      /**
 213       *    Set the value for a cell, with the explicit data type passed to the method (bypassing any use of the value binder)
 214       *
 215       *    @param    mixed    $pValue            Value
 216       *    @param    string    $pDataType        Explicit data type
 217       *    @return    PHPExcel_Cell
 218       *    @throws    PHPExcel_Exception
 219       */
 220      public function setValueExplicit($pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
 221      {
 222          // set the value according to data type
 223          switch ($pDataType) {
 224              case PHPExcel_Cell_DataType::TYPE_NULL:
 225                  $this->value = $pValue;
 226                  break;
 227              case PHPExcel_Cell_DataType::TYPE_STRING2:
 228                  $pDataType = PHPExcel_Cell_DataType::TYPE_STRING;
 229                  // no break
 230              case PHPExcel_Cell_DataType::TYPE_STRING:
 231                  // Synonym for string
 232              case PHPExcel_Cell_DataType::TYPE_INLINE:
 233                  // Rich text
 234                  $this->value = PHPExcel_Cell_DataType::checkString($pValue);
 235                  break;
 236              case PHPExcel_Cell_DataType::TYPE_NUMERIC:
 237                  $this->value = (float) $pValue;
 238                  break;
 239              case PHPExcel_Cell_DataType::TYPE_FORMULA:
 240                  $this->value = (string) $pValue;
 241                  break;
 242              case PHPExcel_Cell_DataType::TYPE_BOOL:
 243                  $this->value = (bool) $pValue;
 244                  break;
 245              case PHPExcel_Cell_DataType::TYPE_ERROR:
 246                  $this->value = PHPExcel_Cell_DataType::checkErrorCode($pValue);
 247                  break;
 248              default:
 249                  throw new PHPExcel_Exception('Invalid datatype: ' . $pDataType);
 250                  break;
 251          }
 252  
 253          // set the datatype
 254          $this->dataType = $pDataType;
 255  
 256          return $this->notifyCacheController();
 257      }
 258  
 259      /**
 260       *    Get calculated cell value
 261       *
 262       *    @deprecated        Since version 1.7.8 for planned changes to cell for array formula handling
 263       *
 264       *    @param    boolean $resetLog  Whether the calculation engine logger should be reset or not
 265       *    @return    mixed
 266       *    @throws    PHPExcel_Exception
 267       */
 268      public function getCalculatedValue($resetLog = true)
 269      {
 270  //echo 'Cell '.$this->getCoordinate().' value is a '.$this->dataType.' with a value of '.$this->getValue().PHP_EOL;
 271          if ($this->dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) {
 272              try {
 273  //echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value'.PHP_EOL;
 274                  $result = PHPExcel_Calculation::getInstance(
 275                      $this->getWorksheet()->getParent()
 276                  )->calculateCellValue($this, $resetLog);
 277  //echo $this->getCoordinate().' calculation result is '.$result.PHP_EOL;
 278                  //    We don't yet handle array returns
 279                  if (is_array($result)) {
 280                      while (is_array($result)) {
 281                          $result = array_pop($result);
 282                      }
 283                  }
 284              } catch (PHPExcel_Exception $ex) {
 285                  if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->calculatedValue !== null)) {
 286  //echo 'Returning fallback value of '.$this->calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL;
 287                      return $this->calculatedValue; // Fallback for calculations referencing external files.
 288                  }
 289  //echo 'Calculation Exception: '.$ex->getMessage().PHP_EOL;
 290                  $result = '#N/A';
 291                  throw new PHPExcel_Calculation_Exception(
 292                      $this->getWorksheet()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage()
 293                  );
 294              }
 295  
 296              if ($result === '#Not Yet Implemented') {
 297  //echo 'Returning fallback value of '.$this->calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL;
 298                  return $this->calculatedValue; // Fallback if calculation engine does not support the formula.
 299              }
 300  //echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().PHP_EOL;
 301              return $result;
 302          } elseif ($this->value instanceof PHPExcel_RichText) {
 303  //        echo 'Cell value for '.$this->getCoordinate().' is rich text: Returning data value of '.$this->value.'<br />';
 304              return $this->value->getPlainText();
 305          }
 306  //        echo 'Cell value for '.$this->getCoordinate().' is not a formula: Returning data value of '.$this->value.'<br />';
 307          return $this->value;
 308      }
 309  
 310      /**
 311       *    Set old calculated value (cached)
 312       *
 313       *    @param    mixed $pValue    Value
 314       *    @return    PHPExcel_Cell
 315       */
 316      public function setCalculatedValue($pValue = null)
 317      {
 318          if ($pValue !== null) {
 319              $this->calculatedValue = (is_numeric($pValue)) ? (float) $pValue : $pValue;
 320          }
 321  
 322          return $this->notifyCacheController();
 323      }
 324  
 325      /**
 326       *    Get old calculated value (cached)
 327       *    This returns the value last calculated by MS Excel or whichever spreadsheet program was used to
 328       *        create the original spreadsheet file.
 329       *    Note that this value is not guaranteed to refelect the actual calculated value because it is
 330       *        possible that auto-calculation was disabled in the original spreadsheet, and underlying data
 331       *        values used by the formula have changed since it was last calculated.
 332       *
 333       *    @return    mixed
 334       */
 335      public function getOldCalculatedValue()
 336      {
 337          return $this->calculatedValue;
 338      }
 339  
 340      /**
 341       *    Get cell data type
 342       *
 343       *    @return string
 344       */
 345      public function getDataType()
 346      {
 347          return $this->dataType;
 348      }
 349  
 350      /**
 351       *    Set cell data type
 352       *
 353       *    @param    string $pDataType
 354       *    @return    PHPExcel_Cell
 355       */
 356      public function setDataType($pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
 357      {
 358          if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2) {
 359              $pDataType = PHPExcel_Cell_DataType::TYPE_STRING;
 360          }
 361          $this->dataType = $pDataType;
 362  
 363          return $this->notifyCacheController();
 364      }
 365  
 366      /**
 367       *  Identify if the cell contains a formula
 368       *
 369       *  @return boolean
 370       */
 371      public function isFormula()
 372      {
 373          return $this->dataType == PHPExcel_Cell_DataType::TYPE_FORMULA;
 374      }
 375  
 376      /**
 377       *    Does this cell contain Data validation rules?
 378       *
 379       *    @return    boolean
 380       *    @throws    PHPExcel_Exception
 381       */
 382      public function hasDataValidation()
 383      {
 384          if (!isset($this->parent)) {
 385              throw new PHPExcel_Exception('Cannot check for data validation when cell is not bound to a worksheet');
 386          }
 387  
 388          return $this->getWorksheet()->dataValidationExists($this->getCoordinate());
 389      }
 390  
 391      /**
 392       *    Get Data validation rules
 393       *
 394       *    @return    PHPExcel_Cell_DataValidation
 395       *    @throws    PHPExcel_Exception
 396       */
 397      public function getDataValidation()
 398      {
 399          if (!isset($this->parent)) {
 400              throw new PHPExcel_Exception('Cannot get data validation for cell that is not bound to a worksheet');
 401          }
 402  
 403          return $this->getWorksheet()->getDataValidation($this->getCoordinate());
 404      }
 405  
 406      /**
 407       *    Set Data validation rules
 408       *
 409       *    @param    PHPExcel_Cell_DataValidation    $pDataValidation
 410       *    @return    PHPExcel_Cell
 411       *    @throws    PHPExcel_Exception
 412       */
 413      public function setDataValidation(PHPExcel_Cell_DataValidation $pDataValidation = null)
 414      {
 415          if (!isset($this->parent)) {
 416              throw new PHPExcel_Exception('Cannot set data validation for cell that is not bound to a worksheet');
 417          }
 418  
 419          $this->getWorksheet()->setDataValidation($this->getCoordinate(), $pDataValidation);
 420  
 421          return $this->notifyCacheController();
 422      }
 423  
 424      /**
 425       *    Does this cell contain a Hyperlink?
 426       *
 427       *    @return boolean
 428       *    @throws    PHPExcel_Exception
 429       */
 430      public function hasHyperlink()
 431      {
 432          if (!isset($this->parent)) {
 433              throw new PHPExcel_Exception('Cannot check for hyperlink when cell is not bound to a worksheet');
 434          }
 435  
 436          return $this->getWorksheet()->hyperlinkExists($this->getCoordinate());
 437      }
 438  
 439      /**
 440       *    Get Hyperlink
 441       *
 442       *    @return    PHPExcel_Cell_Hyperlink
 443       *    @throws    PHPExcel_Exception
 444       */
 445      public function getHyperlink()
 446      {
 447          if (!isset($this->parent)) {
 448              throw new PHPExcel_Exception('Cannot get hyperlink for cell that is not bound to a worksheet');
 449          }
 450  
 451          return $this->getWorksheet()->getHyperlink($this->getCoordinate());
 452      }
 453  
 454      /**
 455       *    Set Hyperlink
 456       *
 457       *    @param    PHPExcel_Cell_Hyperlink    $pHyperlink
 458       *    @return    PHPExcel_Cell
 459       *    @throws    PHPExcel_Exception
 460       */
 461      public function setHyperlink(PHPExcel_Cell_Hyperlink $pHyperlink = null)
 462      {
 463          if (!isset($this->parent)) {
 464              throw new PHPExcel_Exception('Cannot set hyperlink for cell that is not bound to a worksheet');
 465          }
 466  
 467          $this->getWorksheet()->setHyperlink($this->getCoordinate(), $pHyperlink);
 468  
 469          return $this->notifyCacheController();
 470      }
 471  
 472      /**
 473       *    Get parent worksheet
 474       *
 475       *    @return PHPExcel_CachedObjectStorage_CacheBase
 476       */
 477      public function getParent()
 478      {
 479          return $this->parent;
 480      }
 481  
 482      /**
 483       *    Get parent worksheet
 484       *
 485       *    @return PHPExcel_Worksheet
 486       */
 487      public function getWorksheet()
 488      {
 489          return $this->parent->getParent();
 490      }
 491  
 492      /**
 493       *    Is this cell in a merge range
 494       *
 495       *    @return boolean
 496       */
 497      public function isInMergeRange()
 498      {
 499          return (boolean) $this->getMergeRange();
 500      }
 501  
 502      /**
 503       *    Is this cell the master (top left cell) in a merge range (that holds the actual data value)
 504       *
 505       *    @return boolean
 506       */
 507      public function isMergeRangeValueCell()
 508      {
 509          if ($mergeRange = $this->getMergeRange()) {
 510              $mergeRange = PHPExcel_Cell::splitRange($mergeRange);
 511              list($startCell) = $mergeRange[0];
 512              if ($this->getCoordinate() === $startCell) {
 513                  return true;
 514              }
 515          }
 516          return false;
 517      }
 518  
 519      /**
 520       *    If this cell is in a merge range, then return the range
 521       *
 522       *    @return string
 523       */
 524      public function getMergeRange()
 525      {
 526          foreach ($this->getWorksheet()->getMergeCells() as $mergeRange) {
 527              if ($this->isInRange($mergeRange)) {
 528                  return $mergeRange;
 529              }
 530          }
 531          return false;
 532      }
 533  
 534      /**
 535       *    Get cell style
 536       *
 537       *    @return    PHPExcel_Style
 538       */
 539      public function getStyle()
 540      {
 541          return $this->getWorksheet()->getStyle($this->getCoordinate());
 542      }
 543  
 544      /**
 545       *    Re-bind parent
 546       *
 547       *    @param    PHPExcel_Worksheet $parent
 548       *    @return    PHPExcel_Cell
 549       */
 550      public function rebindParent(PHPExcel_Worksheet $parent)
 551      {
 552          $this->parent = $parent->getCellCacheController();
 553  
 554          return $this->notifyCacheController();
 555      }
 556  
 557      /**
 558       *    Is cell in a specific range?
 559       *
 560       *    @param    string    $pRange        Cell range (e.g. A1:A1)
 561       *    @return    boolean
 562       */
 563      public function isInRange($pRange = 'A1:A1')
 564      {
 565          list($rangeStart, $rangeEnd) = self::rangeBoundaries($pRange);
 566  
 567          // Translate properties
 568          $myColumn = self::columnIndexFromString($this->getColumn());
 569          $myRow    = $this->getRow();
 570  
 571          // Verify if cell is in range
 572          return (($rangeStart[0] <= $myColumn) && ($rangeEnd[0] >= $myColumn) &&
 573                  ($rangeStart[1] <= $myRow) && ($rangeEnd[1] >= $myRow)
 574                 );
 575      }
 576  
 577      /**
 578       *    Coordinate from string
 579       *
 580       *    @param    string    $pCoordinateString
 581       *    @return    array    Array containing column and row (indexes 0 and 1)
 582       *    @throws    PHPExcel_Exception
 583       */
 584      public static function coordinateFromString($pCoordinateString = 'A1')
 585      {
 586          if (preg_match("/^([$]?[A-Z]{1,3})([$]?\d{1,7})$/", $pCoordinateString, $matches)) {
 587              return array($matches[1],$matches[2]);
 588          } elseif ((strpos($pCoordinateString, ':') !== false) || (strpos($pCoordinateString, ',') !== false)) {
 589              throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells');
 590          } elseif ($pCoordinateString == '') {
 591              throw new PHPExcel_Exception('Cell coordinate can not be zero-length string');
 592          }
 593  
 594          throw new PHPExcel_Exception('Invalid cell coordinate '.$pCoordinateString);
 595      }
 596  
 597      /**
 598       *    Make string row, column or cell coordinate absolute
 599       *
 600       *    @param    string    $pCoordinateString        e.g. 'A' or '1' or 'A1'
 601       *                    Note that this value can be a row or column reference as well as a cell reference
 602       *    @return    string    Absolute coordinate        e.g. '$A' or '$1' or '$A$1'
 603       *    @throws    PHPExcel_Exception
 604       */
 605      public static function absoluteReference($pCoordinateString = 'A1')
 606      {
 607          if (strpos($pCoordinateString, ':') === false && strpos($pCoordinateString, ',') === false) {
 608              // Split out any worksheet name from the reference
 609              $worksheet = '';
 610              $cellAddress = explode('!', $pCoordinateString);
 611              if (count($cellAddress) > 1) {
 612                  list($worksheet, $pCoordinateString) = $cellAddress;
 613              }
 614              if ($worksheet > '') {
 615                  $worksheet .= '!';
 616              }
 617  
 618              // Create absolute coordinate
 619              if (ctype_digit($pCoordinateString)) {
 620                  return $worksheet . '$' . $pCoordinateString;
 621              } elseif (ctype_alpha($pCoordinateString)) {
 622                  return $worksheet . '$' . strtoupper($pCoordinateString);
 623              }
 624              return $worksheet . self::absoluteCoordinate($pCoordinateString);
 625          }
 626  
 627          throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells');
 628      }
 629  
 630      /**
 631       *    Make string coordinate absolute
 632       *
 633       *    @param    string    $pCoordinateString        e.g. 'A1'
 634       *    @return    string    Absolute coordinate        e.g. '$A$1'
 635       *    @throws    PHPExcel_Exception
 636       */
 637      public static function absoluteCoordinate($pCoordinateString = 'A1')
 638      {
 639          if (strpos($pCoordinateString, ':') === false && strpos($pCoordinateString, ',') === false) {
 640              // Split out any worksheet name from the coordinate
 641              $worksheet = '';
 642              $cellAddress = explode('!', $pCoordinateString);
 643              if (count($cellAddress) > 1) {
 644                  list($worksheet, $pCoordinateString) = $cellAddress;
 645              }
 646              if ($worksheet > '') {
 647                  $worksheet .= '!';
 648              }
 649  
 650              // Create absolute coordinate
 651              list($column, $row) = self::coordinateFromString($pCoordinateString);
 652              $column = ltrim($column, '$');
 653              $row = ltrim($row, '$');
 654              return $worksheet . '$' . $column . '$' . $row;
 655          }
 656  
 657          throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells');
 658      }
 659  
 660      /**
 661       *    Split range into coordinate strings
 662       *
 663       *    @param    string    $pRange        e.g. 'B4:D9' or 'B4:D9,H2:O11' or 'B4'
 664       *    @return    array    Array containg one or more arrays containing one or two coordinate strings
 665       *                                e.g. array('B4','D9') or array(array('B4','D9'),array('H2','O11'))
 666       *                                        or array('B4')
 667       */
 668      public static function splitRange($pRange = 'A1:A1')
 669      {
 670          // Ensure $pRange is a valid range
 671          if (empty($pRange)) {
 672              $pRange = self::DEFAULT_RANGE;
 673          }
 674  
 675          $exploded = explode(',', $pRange);
 676          $counter = count($exploded);
 677          for ($i = 0; $i < $counter; ++$i) {
 678              $exploded[$i] = explode(':', $exploded[$i]);
 679          }
 680          return $exploded;
 681      }
 682  
 683      /**
 684       *    Build range from coordinate strings
 685       *
 686       *    @param    array    $pRange    Array containg one or more arrays containing one or two coordinate strings
 687       *    @return    string    String representation of $pRange
 688       *    @throws    PHPExcel_Exception
 689       */
 690      public static function buildRange($pRange)
 691      {
 692          // Verify range
 693          if (!is_array($pRange) || empty($pRange) || !is_array($pRange[0])) {
 694              throw new PHPExcel_Exception('Range does not contain any information');
 695          }
 696  
 697          // Build range
 698          $imploded = array();
 699          $counter = count($pRange);
 700          for ($i = 0; $i < $counter; ++$i) {
 701              $pRange[$i] = implode(':', $pRange[$i]);
 702          }
 703          $imploded = implode(',', $pRange);
 704  
 705          return $imploded;
 706      }
 707  
 708      /**
 709       *    Calculate range boundaries
 710       *
 711       *    @param    string    $pRange        Cell range (e.g. A1:A1)
 712       *    @return    array    Range coordinates array(Start Cell, End Cell)
 713       *                    where Start Cell and End Cell are arrays (Column Number, Row Number)
 714       */
 715      public static function rangeBoundaries($pRange = 'A1:A1')
 716      {
 717          // Ensure $pRange is a valid range
 718          if (empty($pRange)) {
 719              $pRange = self::DEFAULT_RANGE;
 720          }
 721  
 722          // Uppercase coordinate
 723          $pRange = strtoupper($pRange);
 724  
 725          // Extract range
 726          if (strpos($pRange, ':') === false) {
 727              $rangeA = $rangeB = $pRange;
 728          } else {
 729              list($rangeA, $rangeB) = explode(':', $pRange);
 730          }
 731  
 732          // Calculate range outer borders
 733          $rangeStart = self::coordinateFromString($rangeA);
 734          $rangeEnd    = self::coordinateFromString($rangeB);
 735  
 736          // Translate column into index
 737          $rangeStart[0]    = self::columnIndexFromString($rangeStart[0]);
 738          $rangeEnd[0]    = self::columnIndexFromString($rangeEnd[0]);
 739  
 740          return array($rangeStart, $rangeEnd);
 741      }
 742  
 743      /**
 744       *    Calculate range dimension
 745       *
 746       *    @param    string    $pRange        Cell range (e.g. A1:A1)
 747       *    @return    array    Range dimension (width, height)
 748       */
 749      public static function rangeDimension($pRange = 'A1:A1')
 750      {
 751          // Calculate range outer borders
 752          list($rangeStart, $rangeEnd) = self::rangeBoundaries($pRange);
 753  
 754          return array( ($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1) );
 755      }
 756  
 757      /**
 758       *    Calculate range boundaries
 759       *
 760       *    @param    string    $pRange        Cell range (e.g. A1:A1)
 761       *    @return    array    Range coordinates array(Start Cell, End Cell)
 762       *                    where Start Cell and End Cell are arrays (Column ID, Row Number)
 763       */
 764      public static function getRangeBoundaries($pRange = 'A1:A1')
 765      {
 766          // Ensure $pRange is a valid range
 767          if (empty($pRange)) {
 768              $pRange = self::DEFAULT_RANGE;
 769          }
 770  
 771          // Uppercase coordinate
 772          $pRange = strtoupper($pRange);
 773  
 774          // Extract range
 775          if (strpos($pRange, ':') === false) {
 776              $rangeA = $rangeB = $pRange;
 777          } else {
 778              list($rangeA, $rangeB) = explode(':', $pRange);
 779          }
 780  
 781          return array( self::coordinateFromString($rangeA), self::coordinateFromString($rangeB));
 782      }
 783  
 784      /**
 785       *    Column index from string
 786       *
 787       *    @param    string $pString
 788       *    @return    int Column index (base 1 !!!)
 789       */
 790      public static function columnIndexFromString($pString = 'A')
 791      {
 792          //    Using a lookup cache adds a slight memory overhead, but boosts speed
 793          //    caching using a static within the method is faster than a class static,
 794          //        though it's additional memory overhead
 795          static $_indexCache = array();
 796  
 797          if (isset($_indexCache[$pString])) {
 798              return $_indexCache[$pString];
 799          }
 800          //    It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array rather than use ord()
 801          //        and make it case insensitive to get rid of the strtoupper() as well. Because it's a static, there's no significant
 802          //        memory overhead either
 803          static $_columnLookup = array(
 804              'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, 'I' => 9, 'J' => 10, 'K' => 11, 'L' => 12, 'M' => 13,
 805              'N' => 14, 'O' => 15, 'P' => 16, 'Q' => 17, 'R' => 18, 'S' => 19, 'T' => 20, 'U' => 21, 'V' => 22, 'W' => 23, 'X' => 24, 'Y' => 25, 'Z' => 26,
 806              'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'g' => 7, 'h' => 8, 'i' => 9, 'j' => 10, 'k' => 11, 'l' => 12, 'm' => 13,
 807              'n' => 14, 'o' => 15, 'p' => 16, 'q' => 17, 'r' => 18, 's' => 19, 't' => 20, 'u' => 21, 'v' => 22, 'w' => 23, 'x' => 24, 'y' => 25, 'z' => 26
 808          );
 809  
 810          //    We also use the language construct isset() rather than the more costly strlen() function to match the length of $pString
 811          //        for improved performance
 812          if (isset($pString{0})) {
 813              if (!isset($pString{1})) {
 814                  $_indexCache[$pString] = $_columnLookup[$pString];
 815                  return $_indexCache[$pString];
 816              } elseif (!isset($pString{2})) {
 817                  $_indexCache[$pString] = $_columnLookup[$pString{0}] * 26 + $_columnLookup[$pString{1}];
 818                  return $_indexCache[$pString];
 819              } elseif (!isset($pString{3})) {
 820                  $_indexCache[$pString] = $_columnLookup[$pString{0}] * 676 + $_columnLookup[$pString{1}] * 26 + $_columnLookup[$pString{2}];
 821                  return $_indexCache[$pString];
 822              }
 823          }
 824          throw new PHPExcel_Exception("Column string index can not be " . ((isset($pString{0})) ? "longer than 3 characters" : "empty"));
 825      }
 826  
 827      /**
 828       *    String from columnindex
 829       *
 830       *    @param    int $pColumnIndex Column index (base 0 !!!)
 831       *    @return    string
 832       */
 833      public static function stringFromColumnIndex($pColumnIndex = 0)
 834      {
 835          //    Using a lookup cache adds a slight memory overhead, but boosts speed
 836          //    caching using a static within the method is faster than a class static,
 837          //        though it's additional memory overhead
 838          static $_indexCache = array();
 839  
 840          if (!isset($_indexCache[$pColumnIndex])) {
 841              // Determine column string
 842              if ($pColumnIndex < 26) {
 843                  $_indexCache[$pColumnIndex] = chr(65 + $pColumnIndex);
 844              } elseif ($pColumnIndex < 702) {
 845                  $_indexCache[$pColumnIndex] = chr(64 + ($pColumnIndex / 26)) .
 846                                                chr(65 + $pColumnIndex % 26);
 847              } else {
 848                  $_indexCache[$pColumnIndex] = chr(64 + (($pColumnIndex - 26) / 676)) .
 849                                                chr(65 + ((($pColumnIndex - 26) % 676) / 26)) .
 850                                                chr(65 + $pColumnIndex % 26);
 851              }
 852          }
 853          return $_indexCache[$pColumnIndex];
 854      }
 855  
 856      /**
 857       *    Extract all cell references in range
 858       *
 859       *    @param    string    $pRange        Range (e.g. A1 or A1:C10 or A1:E10 A20:E25)
 860       *    @return    array    Array containing single cell references
 861       */
 862      public static function extractAllCellReferencesInRange($pRange = 'A1')
 863      {
 864          // Returnvalue
 865          $returnValue = array();
 866  
 867          // Explode spaces
 868          $cellBlocks = explode(' ', str_replace('$', '', strtoupper($pRange)));
 869          foreach ($cellBlocks as $cellBlock) {
 870              // Single cell?
 871              if (strpos($cellBlock, ':') === false && strpos($cellBlock, ',') === false) {
 872                  $returnValue[] = $cellBlock;
 873                  continue;
 874              }
 875  
 876              // Range...
 877              $ranges = self::splitRange($cellBlock);
 878              foreach ($ranges as $range) {
 879                  // Single cell?
 880                  if (!isset($range[1])) {
 881                      $returnValue[] = $range[0];
 882                      continue;
 883                  }
 884  
 885                  // Range...
 886                  list($rangeStart, $rangeEnd)    = $range;
 887                  sscanf($rangeStart, '%[A-Z]%d', $startCol, $startRow);
 888                  sscanf($rangeEnd, '%[A-Z]%d', $endCol, $endRow);
 889                  ++$endCol;
 890  
 891                  // Current data
 892                  $currentCol = $startCol;
 893                  $currentRow = $startRow;
 894  
 895                  // Loop cells
 896                  while ($currentCol != $endCol) {
 897                      while ($currentRow <= $endRow) {
 898                          $returnValue[] = $currentCol.$currentRow;
 899                          ++$currentRow;
 900                      }
 901                      ++$currentCol;
 902                      $currentRow = $startRow;
 903                  }
 904              }
 905          }
 906  
 907          //    Sort the result by column and row
 908          $sortKeys = array();
 909          foreach (array_unique($returnValue) as $coord) {
 910              sscanf($coord, '%[A-Z]%d', $column, $row);
 911              $sortKeys[sprintf('%3s%09d', $column, $row)] = $coord;
 912          }
 913          ksort($sortKeys);
 914  
 915          // Return value
 916          return array_values($sortKeys);
 917      }
 918  
 919      /**
 920       * Compare 2 cells
 921       *
 922       * @param    PHPExcel_Cell    $a    Cell a
 923       * @param    PHPExcel_Cell    $b    Cell b
 924       * @return    int        Result of comparison (always -1 or 1, never zero!)
 925       */
 926      public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b)
 927      {
 928          if ($a->getRow() < $b->getRow()) {
 929              return -1;
 930          } elseif ($a->getRow() > $b->getRow()) {
 931              return 1;
 932          } elseif (self::columnIndexFromString($a->getColumn()) < self::columnIndexFromString($b->getColumn())) {
 933              return -1;
 934          } else {
 935              return 1;
 936          }
 937      }
 938  
 939      /**
 940       * Get value binder to use
 941       *
 942       * @return PHPExcel_Cell_IValueBinder
 943       */
 944      public static function getValueBinder()
 945      {
 946          if (self::$valueBinder === null) {
 947              self::$valueBinder = new PHPExcel_Cell_DefaultValueBinder();
 948          }
 949  
 950          return self::$valueBinder;
 951      }
 952  
 953      /**
 954       * Set value binder to use
 955       *
 956       * @param PHPExcel_Cell_IValueBinder $binder
 957       * @throws PHPExcel_Exception
 958       */
 959      public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = null)
 960      {
 961          if ($binder === null) {
 962              throw new PHPExcel_Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly.");
 963          }
 964  
 965          self::$valueBinder = $binder;
 966      }
 967  
 968      /**
 969       * Implement PHP __clone to create a deep clone, not just a shallow copy.
 970       */
 971      public function __clone()
 972      {
 973          $vars = get_object_vars($this);
 974          foreach ($vars as $key => $value) {
 975              if ((is_object($value)) && ($key != 'parent')) {
 976                  $this->$key = clone $value;
 977              } else {
 978                  $this->$key = $value;
 979              }
 980          }
 981      }
 982  
 983      /**
 984       * Get index to cellXf
 985       *
 986       * @return int
 987       */
 988      public function getXfIndex()
 989      {
 990          return $this->xfIndex;
 991      }
 992  
 993      /**
 994       * Set index to cellXf
 995       *
 996       * @param int $pValue
 997       * @return PHPExcel_Cell
 998       */
 999      public function setXfIndex($pValue = 0)
1000      {
1001          $this->xfIndex = $pValue;
1002  
1003          return $this->notifyCacheController();
1004      }
1005  
1006      /**
1007       *    @deprecated        Since version 1.7.8 for planned changes to cell for array formula handling
1008       */
1009      public function setFormulaAttributes($pAttributes)
1010      {
1011          $this->formulaAttributes = $pAttributes;
1012          return $this;
1013      }
1014  
1015      /**
1016       *    @deprecated        Since version 1.7.8 for planned changes to cell for array formula handling
1017       */
1018      public function getFormulaAttributes()
1019      {
1020          return $this->formulaAttributes;
1021      }
1022  
1023      /**
1024       * Convert to string
1025       *
1026       * @return string
1027       */
1028      public function __toString()
1029      {
1030          return (string) $this->getValue();
1031      }
1032  }


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