[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |