PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Classes/PHPExcel/Cell.php

https://bitbucket.org/tedbundyjr/phpexcel
PHP | 896 lines | 419 code | 109 blank | 368 comment | 71 complexity | 7a5146b57d62fc40fa00310ac2222a05 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2012 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Cell
  23. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version 1.7.7, 2012-05-19
  26. */
  27. /**
  28. * PHPExcel_Cell
  29. *
  30. * @category PHPExcel
  31. * @package PHPExcel_Cell
  32. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  33. */
  34. class PHPExcel_Cell
  35. {
  36. /**
  37. * Value binder to use
  38. *
  39. * @var PHPExcel_Cell_IValueBinder
  40. */
  41. private static $_valueBinder = null;
  42. /**
  43. * Column of the cell
  44. *
  45. * @var string
  46. */
  47. private $_column;
  48. /**
  49. * Row of the cell
  50. *
  51. * @var int
  52. */
  53. private $_row;
  54. /**
  55. * Value of the cell
  56. *
  57. * @var mixed
  58. */
  59. private $_value;
  60. /**
  61. * Calculated value of the cell (used for caching)
  62. *
  63. * @var mixed
  64. */
  65. private $_calculatedValue = null;
  66. /**
  67. * Type of the cell data
  68. *
  69. * @var string
  70. */
  71. private $_dataType;
  72. /**
  73. * Parent worksheet
  74. *
  75. * @var PHPExcel_Worksheet
  76. */
  77. private $_parent;
  78. /**
  79. * Index to cellXf
  80. *
  81. * @var int
  82. */
  83. private $_xfIndex;
  84. /**
  85. * Attributes of the formula
  86. *
  87. *
  88. */
  89. private $_formulaAttributes;
  90. /**
  91. * Send notification to the cache controller
  92. *
  93. * @return void
  94. **/
  95. public function notifyCacheController() {
  96. $this->_parent->getCellCacheController()->updateCacheData($this);
  97. return $this;
  98. }
  99. public function detach() {
  100. $this->_parent = null;
  101. }
  102. public function attach($parent) {
  103. $this->_parent = $parent;
  104. }
  105. /**
  106. * Create a new Cell
  107. *
  108. * @param string $pColumn
  109. * @param int $pRow
  110. * @param mixed $pValue
  111. * @param string $pDataType
  112. * @param PHPExcel_Worksheet $pSheet
  113. * @throws Exception
  114. */
  115. public function __construct($pColumn = 'A', $pRow = 1, $pValue = null, $pDataType = null, PHPExcel_Worksheet $pSheet = null)
  116. {
  117. // Initialise cell coordinate
  118. $this->_column = strtoupper($pColumn);
  119. $this->_row = $pRow;
  120. // Initialise cell value
  121. $this->_value = $pValue;
  122. // Set worksheet
  123. $this->_parent = $pSheet;
  124. // Set datatype?
  125. if ($pDataType !== null) {
  126. if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2)
  127. $pDataType = PHPExcel_Cell_DataType::TYPE_STRING;
  128. $this->_dataType = $pDataType;
  129. } else {
  130. if (!self::getValueBinder()->bindValue($this, $pValue)) {
  131. throw new Exception("Value could not be bound to cell.");
  132. }
  133. }
  134. // set default index to cellXf
  135. $this->_xfIndex = 0;
  136. }
  137. /**
  138. * Get cell coordinate column
  139. *
  140. * @return string
  141. */
  142. public function getColumn()
  143. {
  144. return $this->_column;
  145. }
  146. /**
  147. * Get cell coordinate row
  148. *
  149. * @return int
  150. */
  151. public function getRow()
  152. {
  153. return $this->_row;
  154. }
  155. /**
  156. * Get cell coordinate
  157. *
  158. * @return string
  159. */
  160. public function getCoordinate()
  161. {
  162. return $this->_column . $this->_row;
  163. }
  164. /**
  165. * Get cell value
  166. *
  167. * @return mixed
  168. */
  169. public function getValue()
  170. {
  171. return $this->_value;
  172. }
  173. /**
  174. * Get cell value with formatting
  175. *
  176. * @return string
  177. */
  178. public function getFormattedValue()
  179. {
  180. return (string) PHPExcel_Style_NumberFormat::toFormattedString( $this->getCalculatedValue(),
  181. $this->_parent->getParent()->getCellXfByIndex($this->getXfIndex())->getNumberFormat()->getFormatCode()
  182. );
  183. }
  184. /**
  185. * Set cell value
  186. *
  187. * Sets the value for a cell, automatically determining the datatype using the value binder
  188. *
  189. * @param mixed $pValue Value
  190. * @return PHPExcel_Cell
  191. */
  192. public function setValue($pValue = null)
  193. {
  194. if (!self::getValueBinder()->bindValue($this, $pValue)) {
  195. throw new Exception("Value could not be bound to cell.");
  196. }
  197. return $this;
  198. }
  199. /**
  200. * Set the value for a cell, with the explicit data type passed to the method (bypassing any use of the value binder)
  201. *
  202. * @param mixed $pValue Value
  203. * @param string $pDataType Explicit data type
  204. * @return PHPExcel_Cell
  205. * @throws Exception
  206. */
  207. public function setValueExplicit($pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
  208. {
  209. // set the value according to data type
  210. switch ($pDataType) {
  211. case PHPExcel_Cell_DataType::TYPE_STRING2:
  212. $pDataType = PHPExcel_Cell_DataType::TYPE_STRING;
  213. case PHPExcel_Cell_DataType::TYPE_STRING:
  214. case PHPExcel_Cell_DataType::TYPE_NULL:
  215. case PHPExcel_Cell_DataType::TYPE_INLINE:
  216. $this->_value = PHPExcel_Cell_DataType::checkString($pValue);
  217. break;
  218. case PHPExcel_Cell_DataType::TYPE_NUMERIC:
  219. $this->_value = (float)$pValue;
  220. break;
  221. case PHPExcel_Cell_DataType::TYPE_FORMULA:
  222. $this->_value = (string)$pValue;
  223. break;
  224. case PHPExcel_Cell_DataType::TYPE_BOOL:
  225. $this->_value = (bool)$pValue;
  226. break;
  227. case PHPExcel_Cell_DataType::TYPE_ERROR:
  228. $this->_value = PHPExcel_Cell_DataType::checkErrorCode($pValue);
  229. break;
  230. default:
  231. throw new Exception('Invalid datatype: ' . $pDataType);
  232. break;
  233. }
  234. // set the datatype
  235. $this->_dataType = $pDataType;
  236. return $this->notifyCacheController();
  237. }
  238. /**
  239. * Get calculated cell value
  240. *
  241. * @return mixed
  242. */
  243. public function getCalculatedValue($resetLog=true)
  244. {
  245. // echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().'<br />';
  246. if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) {
  247. try {
  248. // echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value<br />';
  249. $result = PHPExcel_Calculation::getInstance()->calculateCellValue($this,$resetLog);
  250. // echo $this->getCoordinate().' calculation result is '.$result.'<br />';
  251. } catch ( Exception $ex ) {
  252. if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) {
  253. // echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'<br />';
  254. return $this->_calculatedValue; // Fallback for calculations referencing external files.
  255. }
  256. // echo 'Calculation Exception: '.$ex->getMessage().'<br />';
  257. $result = '#N/A';
  258. throw(new Exception($this->getParent()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage()));
  259. }
  260. if ($result === '#Not Yet Implemented') {
  261. // echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'<br />';
  262. return $this->_calculatedValue; // Fallback if calculation engine does not support the formula.
  263. }
  264. // echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().'<br />';
  265. return $result;
  266. }
  267. // if ($this->_value === NULL) {
  268. // echo 'Cell '.$this->getCoordinate().' has no value, formula or otherwise<br />';
  269. // return null;
  270. // }
  271. // echo 'Cell value for '.$this->getCoordinate().' is not a formula: Returning data value of '.$this->_value.'<br />';
  272. return $this->_value;
  273. }
  274. /**
  275. * Set calculated value (used for caching)
  276. *
  277. * @param mixed $pValue Value
  278. * @return PHPExcel_Cell
  279. */
  280. public function setCalculatedValue($pValue = null)
  281. {
  282. if ($pValue !== NULL) {
  283. $this->_calculatedValue = (is_numeric($pValue)) ? (float) $pValue : $pValue;
  284. }
  285. return $this->notifyCacheController();
  286. }
  287. /**
  288. * Get old calculated value (cached)
  289. *
  290. * @return mixed
  291. */
  292. public function getOldCalculatedValue()
  293. {
  294. return $this->_calculatedValue;
  295. }
  296. /**
  297. * Get cell data type
  298. *
  299. * @return string
  300. */
  301. public function getDataType()
  302. {
  303. return $this->_dataType;
  304. }
  305. /**
  306. * Set cell data type
  307. *
  308. * @param string $pDataType
  309. * @return PHPExcel_Cell
  310. */
  311. public function setDataType($pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
  312. {
  313. if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2)
  314. $pDataType = PHPExcel_Cell_DataType::TYPE_STRING;
  315. $this->_dataType = $pDataType;
  316. return $this->notifyCacheController();
  317. }
  318. /**
  319. * Has Data validation?
  320. *
  321. * @return boolean
  322. */
  323. public function hasDataValidation()
  324. {
  325. if (!isset($this->_parent)) {
  326. throw new Exception('Cannot check for data validation when cell is not bound to a worksheet');
  327. }
  328. return $this->_parent->dataValidationExists($this->getCoordinate());
  329. }
  330. /**
  331. * Get Data validation
  332. *
  333. * @return PHPExcel_Cell_DataValidation
  334. */
  335. public function getDataValidation()
  336. {
  337. if (!isset($this->_parent)) {
  338. throw new Exception('Cannot get data validation for cell that is not bound to a worksheet');
  339. }
  340. return $this->_parent->getDataValidation($this->getCoordinate());
  341. }
  342. /**
  343. * Set Data validation
  344. *
  345. * @param PHPExcel_Cell_DataValidation $pDataValidation
  346. * @throws Exception
  347. * @return PHPExcel_Cell
  348. */
  349. public function setDataValidation(PHPExcel_Cell_DataValidation $pDataValidation = null)
  350. {
  351. if (!isset($this->_parent)) {
  352. throw new Exception('Cannot set data validation for cell that is not bound to a worksheet');
  353. }
  354. $this->_parent->setDataValidation($this->getCoordinate(), $pDataValidation);
  355. return $this->notifyCacheController();
  356. }
  357. /**
  358. * Has Hyperlink
  359. *
  360. * @return boolean
  361. */
  362. public function hasHyperlink()
  363. {
  364. if (!isset($this->_parent)) {
  365. throw new Exception('Cannot check for hyperlink when cell is not bound to a worksheet');
  366. }
  367. return $this->_parent->hyperlinkExists($this->getCoordinate());
  368. }
  369. /**
  370. * Get Hyperlink
  371. *
  372. * @throws Exception
  373. * @return PHPExcel_Cell_Hyperlink
  374. */
  375. public function getHyperlink()
  376. {
  377. if (!isset($this->_parent)) {
  378. throw new Exception('Cannot get hyperlink for cell that is not bound to a worksheet');
  379. }
  380. return $this->_parent->getHyperlink($this->getCoordinate());
  381. }
  382. /**
  383. * Set Hyperlink
  384. *
  385. * @param PHPExcel_Cell_Hyperlink $pHyperlink
  386. * @throws Exception
  387. * @return PHPExcel_Cell
  388. */
  389. public function setHyperlink(PHPExcel_Cell_Hyperlink $pHyperlink = null)
  390. {
  391. if (!isset($this->_parent)) {
  392. throw new Exception('Cannot set hyperlink for cell that is not bound to a worksheet');
  393. }
  394. $this->_parent->setHyperlink($this->getCoordinate(), $pHyperlink);
  395. return $this->notifyCacheController();
  396. }
  397. /**
  398. * Get parent
  399. *
  400. * @return PHPExcel_Worksheet
  401. */
  402. public function getParent() {
  403. return $this->_parent;
  404. }
  405. /**
  406. * Re-bind parent
  407. *
  408. * @param PHPExcel_Worksheet $parent
  409. * @return PHPExcel_Cell
  410. */
  411. public function rebindParent(PHPExcel_Worksheet $parent) {
  412. $this->_parent = $parent;
  413. return $this->notifyCacheController();
  414. }
  415. /**
  416. * Is cell in a specific range?
  417. *
  418. * @param string $pRange Cell range (e.g. A1:A1)
  419. * @return boolean
  420. */
  421. public function isInRange($pRange = 'A1:A1')
  422. {
  423. list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange);
  424. // Translate properties
  425. $myColumn = PHPExcel_Cell::columnIndexFromString($this->getColumn());
  426. $myRow = $this->getRow();
  427. // Verify if cell is in range
  428. return (($rangeStart[0] <= $myColumn) && ($rangeEnd[0] >= $myColumn) &&
  429. ($rangeStart[1] <= $myRow) && ($rangeEnd[1] >= $myRow)
  430. );
  431. }
  432. /**
  433. * Coordinate from string
  434. *
  435. * @param string $pCoordinateString
  436. * @return array Array containing column and row (indexes 0 and 1)
  437. * @throws Exception
  438. */
  439. public static function coordinateFromString($pCoordinateString = 'A1')
  440. {
  441. if (preg_match("/^([$]?[A-Z]{1,3})([$]?\d{1,7})$/", $pCoordinateString, $matches)) {
  442. return array($matches[1],$matches[2]);
  443. } elseif ((strpos($pCoordinateString,':') !== false) || (strpos($pCoordinateString,',') !== false)) {
  444. throw new Exception('Cell coordinate string can not be a range of cells.');
  445. } elseif ($pCoordinateString == '') {
  446. throw new Exception('Cell coordinate can not be zero-length string.');
  447. } else {
  448. throw new Exception('Invalid cell coordinate '.$pCoordinateString);
  449. }
  450. }
  451. /**
  452. * Make string row, column or cell coordinate absolute
  453. *
  454. * @param string $pCoordinateString e.g. 'A' or '1' or 'A1'
  455. * @return string Absolute coordinate e.g. '$A' or '$1' or '$A$1'
  456. * @throws Exception
  457. */
  458. public static function absoluteReference($pCoordinateString = 'A1')
  459. {
  460. if (strpos($pCoordinateString,':') === false && strpos($pCoordinateString,',') === false) {
  461. // Create absolute coordinate
  462. if (ctype_digit($pCoordinateString)) {
  463. return '$'.$pCoordinateString;
  464. } elseif (ctype_alpha($pCoordinateString)) {
  465. return '$'.strtoupper($pCoordinateString);
  466. }
  467. return self::absoluteCoordinate($pCoordinateString);
  468. } else {
  469. throw new Exception("Coordinate string should not be a cell range.");
  470. }
  471. }
  472. /**
  473. * Make string coordinate absolute
  474. *
  475. * @param string $pCoordinateString e.g. 'A1'
  476. * @return string Absolute coordinate e.g. '$A$1'
  477. * @throws Exception
  478. */
  479. public static function absoluteCoordinate($pCoordinateString = 'A1')
  480. {
  481. if (strpos($pCoordinateString,':') === false && strpos($pCoordinateString,',') === false) {
  482. // Create absolute coordinate
  483. $worksheet = '';
  484. $cellAddress = explode('!',$pCoordinateString);
  485. if (count($cellAddress) == 2) {
  486. list($worksheet,$pCoordinateString) = $cellAddress;
  487. }
  488. list($column, $row) = PHPExcel_Cell::coordinateFromString($pCoordinateString);
  489. if ($column[0] == '$') $column = substr($column,1);
  490. if ($row[0] == '$') $row = substr($row,1);
  491. if ($worksheet > '')
  492. $worksheet .= '!';
  493. return $worksheet . '$' . $column . '$' . $row;
  494. } else {
  495. throw new Exception("Coordinate string should not be a cell range.");
  496. }
  497. }
  498. /**
  499. * Split range into coordinate strings
  500. *
  501. * @param string $pRange
  502. * @return array Array containg one or more arrays containing one or two coordinate strings
  503. */
  504. public static function splitRange($pRange = 'A1:A1')
  505. {
  506. $exploded = explode(',', $pRange);
  507. $counter = count($exploded);
  508. for ($i = 0; $i < $counter; ++$i) {
  509. $exploded[$i] = explode(':', $exploded[$i]);
  510. }
  511. return $exploded;
  512. }
  513. /**
  514. * Build range from coordinate strings
  515. *
  516. * @param array $pRange Array containg one or more arrays containing one or two coordinate strings
  517. * @return string String representation of $pRange
  518. * @throws Exception
  519. */
  520. public static function buildRange($pRange)
  521. {
  522. // Verify range
  523. if (!is_array($pRange) || empty($pRange) || !is_array($pRange[0])) {
  524. throw new Exception('Range does not contain any information.');
  525. }
  526. // Build range
  527. $imploded = array();
  528. $counter = count($pRange);
  529. for ($i = 0; $i < $counter; ++$i) {
  530. $pRange[$i] = implode(':', $pRange[$i]);
  531. }
  532. $imploded = implode(',', $pRange);
  533. return $imploded;
  534. }
  535. /**
  536. * Calculate range boundaries
  537. *
  538. * @param string $pRange Cell range (e.g. A1:A1)
  539. * @return array Range coordinates (Start Cell, End Cell) where Start Cell and End Cell are arrays (Column Number, Row Number)
  540. */
  541. public static function rangeBoundaries($pRange = 'A1:A1')
  542. {
  543. // Uppercase coordinate
  544. $pRange = strtoupper($pRange);
  545. // Extract range
  546. if (strpos($pRange, ':') === false) {
  547. $rangeA = $rangeB = $pRange;
  548. } else {
  549. list($rangeA, $rangeB) = explode(':', $pRange);
  550. }
  551. // Calculate range outer borders
  552. $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
  553. $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB);
  554. // Translate column into index
  555. $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]);
  556. $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]);
  557. return array($rangeStart, $rangeEnd);
  558. }
  559. /**
  560. * Calculate range dimension
  561. *
  562. * @param string $pRange Cell range (e.g. A1:A1)
  563. * @return array Range dimension (width, height)
  564. */
  565. public static function rangeDimension($pRange = 'A1:A1')
  566. {
  567. // Calculate range outer borders
  568. list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange);
  569. return array( ($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1) );
  570. }
  571. /**
  572. * Calculate range boundaries
  573. *
  574. * @param string $pRange Cell range (e.g. A1:A1)
  575. * @return array Range boundaries (staring Column, starting Row, Final Column, Final Row)
  576. */
  577. public static function getRangeBoundaries($pRange = 'A1:A1')
  578. {
  579. // Uppercase coordinate
  580. $pRange = strtoupper($pRange);
  581. // Extract range
  582. if (strpos($pRange, ':') === false) {
  583. $rangeA = $rangeB = $pRange;
  584. } else {
  585. list($rangeA, $rangeB) = explode(':', $pRange);
  586. }
  587. return array( self::coordinateFromString($rangeA), self::coordinateFromString($rangeB));
  588. }
  589. /**
  590. * Column index from string
  591. *
  592. * @param string $pString
  593. * @return int Column index (base 1 !!!)
  594. * @throws Exception
  595. */
  596. public static function columnIndexFromString($pString = 'A')
  597. {
  598. // Using a lookup cache adds a slight memory overhead, but boosts speed
  599. // caching using a static within the method is faster than a class static,
  600. // though it's additional memory overhead
  601. static $_indexCache = array();
  602. if (isset($_indexCache[$pString]))
  603. return $_indexCache[$pString];
  604. // It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array rather than use ord()
  605. // and make it case insensitive to get rid of the strtoupper() as well. Because it's a static, there's no significant
  606. // memory overhead either
  607. static $_columnLookup = array(
  608. '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,
  609. '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,
  610. '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,
  611. '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
  612. );
  613. // We also use the language construct isset() rather than the more costly strlen() function to match the length of $pString
  614. // for improved performance
  615. if (isset($pString{0})) {
  616. if (!isset($pString{1})) {
  617. $_indexCache[$pString] = $_columnLookup[$pString];
  618. return $_indexCache[$pString];
  619. } elseif(!isset($pString{2})) {
  620. $_indexCache[$pString] = $_columnLookup[$pString{0}] * 26 + $_columnLookup[$pString{1}];
  621. return $_indexCache[$pString];
  622. } elseif(!isset($pString{3})) {
  623. $_indexCache[$pString] = $_columnLookup[$pString{0}] * 676 + $_columnLookup[$pString{1}] * 26 + $_columnLookup[$pString{2}];
  624. return $_indexCache[$pString];
  625. }
  626. }
  627. throw new Exception("Column string index can not be " . ((isset($pString{0})) ? "longer than 3 characters" : "empty") . ".");
  628. }
  629. /**
  630. * String from columnindex
  631. *
  632. * @param int $pColumnIndex Column index (base 0 !!!)
  633. * @return string
  634. */
  635. public static function stringFromColumnIndex($pColumnIndex = 0)
  636. {
  637. // Using a lookup cache adds a slight memory overhead, but boosts speed
  638. // caching using a static within the method is faster than a class static,
  639. // though it's additional memory overhead
  640. static $_indexCache = array();
  641. if (!isset($_indexCache[$pColumnIndex])) {
  642. // Determine column string
  643. if ($pColumnIndex < 26) {
  644. $_indexCache[$pColumnIndex] = chr(65 + $pColumnIndex);
  645. } elseif ($pColumnIndex < 702) {
  646. $_indexCache[$pColumnIndex] = chr(64 + ($pColumnIndex / 26)) .
  647. chr(65 + $pColumnIndex % 26);
  648. } else {
  649. $_indexCache[$pColumnIndex] = chr(64 + (($pColumnIndex - 26) / 676)) .
  650. chr(65 + ((($pColumnIndex - 26) % 676) / 26)) .
  651. chr(65 + $pColumnIndex % 26);
  652. }
  653. }
  654. return $_indexCache[$pColumnIndex];
  655. }
  656. /**
  657. * Extract all cell references in range
  658. *
  659. * @param string $pRange Range (e.g. A1 or A1:A10 or A1:A10 A100:A1000)
  660. * @return array Array containing single cell references
  661. */
  662. public static function extractAllCellReferencesInRange($pRange = 'A1') {
  663. // Returnvalue
  664. $returnValue = array();
  665. // Explode spaces
  666. $cellBlocks = explode(' ', str_replace('$', '', strtoupper($pRange)));
  667. foreach ($cellBlocks as $cellBlock) {
  668. // Single cell?
  669. if (strpos($cellBlock,':') === false && strpos($cellBlock,',') === false) {
  670. $returnValue[] = $cellBlock;
  671. continue;
  672. }
  673. // Range...
  674. $ranges = PHPExcel_Cell::splitRange($cellBlock);
  675. foreach($ranges as $range) {
  676. // Single cell?
  677. if (!isset($range[1])) {
  678. $returnValue[] = $range[0];
  679. continue;
  680. }
  681. // Range...
  682. list($rangeStart, $rangeEnd) = $range;
  683. list($startCol, $startRow) = sscanf($rangeStart,'%[A-Z]%d');
  684. list($endCol, $endRow) = sscanf($rangeEnd,'%[A-Z]%d');
  685. $endCol++;
  686. // Current data
  687. $currentCol = $startCol;
  688. $currentRow = $startRow;
  689. // Loop cells
  690. while ($currentCol != $endCol) {
  691. while ($currentRow <= $endRow) {
  692. $returnValue[] = $currentCol.$currentRow;
  693. ++$currentRow;
  694. }
  695. ++$currentCol;
  696. $currentRow = $startRow;
  697. }
  698. }
  699. }
  700. // Return value
  701. return $returnValue;
  702. }
  703. /**
  704. * Compare 2 cells
  705. *
  706. * @param PHPExcel_Cell $a Cell a
  707. * @param PHPExcel_Cell $a Cell b
  708. * @return int Result of comparison (always -1 or 1, never zero!)
  709. */
  710. public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b)
  711. {
  712. if ($a->_row < $b->_row) {
  713. return -1;
  714. } elseif ($a->_row > $b->_row) {
  715. return 1;
  716. } elseif (PHPExcel_Cell::columnIndexFromString($a->_column) < PHPExcel_Cell::columnIndexFromString($b->_column)) {
  717. return -1;
  718. } else {
  719. return 1;
  720. }
  721. }
  722. /**
  723. * Get value binder to use
  724. *
  725. * @return PHPExcel_Cell_IValueBinder
  726. */
  727. public static function getValueBinder() {
  728. if (self::$_valueBinder === NULL) {
  729. self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder();
  730. }
  731. return self::$_valueBinder;
  732. }
  733. /**
  734. * Set value binder to use
  735. *
  736. * @param PHPExcel_Cell_IValueBinder $binder
  737. * @throws Exception
  738. */
  739. public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = null) {
  740. if ($binder === NULL) {
  741. throw new Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly.");
  742. }
  743. self::$_valueBinder = $binder;
  744. }
  745. /**
  746. * Implement PHP __clone to create a deep clone, not just a shallow copy.
  747. */
  748. public function __clone() {
  749. $vars = get_object_vars($this);
  750. foreach ($vars as $key => $value) {
  751. if ((is_object($value)) && ($key != '_parent')) {
  752. $this->$key = clone $value;
  753. } else {
  754. $this->$key = $value;
  755. }
  756. }
  757. }
  758. /**
  759. * Get index to cellXf
  760. *
  761. * @return int
  762. */
  763. public function getXfIndex()
  764. {
  765. return $this->_xfIndex;
  766. }
  767. /**
  768. * Set index to cellXf
  769. *
  770. * @param int $pValue
  771. * @return PHPExcel_Cell
  772. */
  773. public function setXfIndex($pValue = 0)
  774. {
  775. $this->_xfIndex = $pValue;
  776. return $this->notifyCacheController();
  777. }
  778. public function setFormulaAttributes($pAttributes)
  779. {
  780. $this->_formulaAttributes = $pAttributes;
  781. return $this;
  782. }
  783. public function getFormulaAttributes()
  784. {
  785. return $this->_formulaAttributes;
  786. }
  787. }