PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/branches/wi16-graphs/Classes/PHPExcel/Cell.php

#
PHP | 721 lines | 326 code | 89 blank | 306 comment | 65 complexity | 38ea084c38849e0808897d7e78583efb MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2009 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 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. /** PHPExcel_Cell_DataType */
  28. require_once 'PHPExcel/Cell/DataType.php';
  29. /** PHPExcel_Cell_DataValidation */
  30. require_once 'PHPExcel/Cell/DataValidation.php';
  31. /** PHPExcel_Cell_Hyperlink */
  32. require_once 'PHPExcel/Cell/Hyperlink.php';
  33. /** PHPExcel_Worksheet */
  34. require_once 'PHPExcel/Worksheet.php';
  35. /** PHPExcel_Calculation */
  36. require_once 'PHPExcel/Calculation.php';
  37. /** PHPExcel_Cell_IValueBinder */
  38. require_once 'PHPExcel/Cell/IValueBinder.php';
  39. /** PHPExcel_Cell_DefaultValueBinder */
  40. require_once 'PHPExcel/Cell/DefaultValueBinder.php';
  41. /**
  42. * PHPExcel_Cell
  43. *
  44. * @category PHPExcel
  45. * @package PHPExcel_Cell
  46. * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
  47. */
  48. class PHPExcel_Cell
  49. {
  50. /**
  51. * Value binder to use
  52. *
  53. * @var PHPExcel_Cell_IValueBinder
  54. */
  55. private static $_valueBinder = null;
  56. /**
  57. * Column of the cell
  58. *
  59. * @var string
  60. */
  61. private $_column;
  62. /**
  63. * Row of the cell
  64. *
  65. * @var int
  66. */
  67. private $_row;
  68. /**
  69. * Value of the cell
  70. *
  71. * @var mixed
  72. */
  73. private $_value;
  74. /**
  75. * Calculated value of the cell (used for caching)
  76. *
  77. * @var mixed
  78. */
  79. private $_calculatedValue = null;
  80. /**
  81. * Type of the cell data
  82. *
  83. * @var string
  84. */
  85. private $_dataType;
  86. /**
  87. * Data validation
  88. *
  89. * @var PHPExcel_Cell_DataValidation
  90. */
  91. private $_dataValidation;
  92. /**
  93. * Hyperlink
  94. *
  95. * @var PHPExcel_Cell_Hyperlink
  96. */
  97. private $_hyperlink;
  98. /**
  99. * Parent worksheet
  100. *
  101. * @var PHPExcel_Worksheet
  102. */
  103. private $_parent;
  104. /**
  105. * Create a new Cell
  106. *
  107. * @param string $pColumn
  108. * @param int $pRow
  109. * @param mixed $pValue
  110. * @param string $pDataType
  111. * @param PHPExcel_Worksheet $pSheet
  112. * @throws Exception
  113. */
  114. public function __construct($pColumn = 'A', $pRow = 1, $pValue = null, $pDataType = null, PHPExcel_Worksheet $pSheet = null)
  115. {
  116. // Set value binder?
  117. if (is_null(self::$_valueBinder)) {
  118. self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder();
  119. }
  120. // Initialise cell coordinate
  121. $this->_column = strtoupper($pColumn);
  122. $this->_row = $pRow;
  123. // Initialise cell value
  124. $this->_value = $pValue;
  125. // Set worksheet
  126. $this->_parent = $pSheet;
  127. // Set datatype?
  128. if (!is_null($pDataType)) {
  129. $this->_dataType = $pDataType;
  130. } else {
  131. if (!self::getValueBinder()->bindValue($this, $pValue)) {
  132. throw new Exception("Value could not be bound to cell.");
  133. }
  134. }
  135. }
  136. /**
  137. * Get cell coordinate column
  138. *
  139. * @return string
  140. */
  141. public function getColumn()
  142. {
  143. return strtoupper($this->_column);
  144. }
  145. /**
  146. * Get cell coordinate row
  147. *
  148. * @return int
  149. */
  150. public function getRow()
  151. {
  152. return $this->_row;
  153. }
  154. /**
  155. * Get cell coordinate
  156. *
  157. * @return string
  158. */
  159. public function getCoordinate()
  160. {
  161. return $this->_column . $this->_row;
  162. }
  163. /**
  164. * Get cell value
  165. *
  166. * @return mixed
  167. */
  168. public function getValue()
  169. {
  170. return $this->_value;
  171. }
  172. /**
  173. * Set cell value
  174. *
  175. * This clears the cell formula.
  176. *
  177. * @param mixed $pValue Value
  178. * @param bool $pUpdateDataType Update the data type?
  179. */
  180. public function setValue($pValue = null, $pUpdateDataType = true)
  181. {
  182. $this->_value = $pValue;
  183. if ($pUpdateDataType) {
  184. if (!self::getValueBinder()->bindValue($this, $pValue)) {
  185. throw new Exception("Value could not be bound to cell.");
  186. }
  187. }
  188. }
  189. /**
  190. * Set cell value (with explicit data type given)
  191. *
  192. * @param mixed $pValue Value
  193. * @param string $pDataType Explicit data type
  194. */
  195. public function setValueExplicit($pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
  196. {
  197. $this->_value = $pValue;
  198. $this->_dataType = $pDataType;
  199. }
  200. /**
  201. * Get caluclated cell value
  202. *
  203. * @return mixed
  204. */
  205. public function getCalculatedValue()
  206. {
  207. if (!is_null($this->_calculatedValue) && $this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) {
  208. try {
  209. $result = PHPExcel_Calculation::getInstance()->calculate($this);
  210. } catch ( Exception $ex ) {
  211. $result = '#N/A';
  212. }
  213. if ((is_string($result)) && ($result == '#Not Yet Implemented')) {
  214. return $this->_calculatedValue; // Fallback if calculation engine does not support the formula.
  215. } else {
  216. return $result;
  217. }
  218. }
  219. if (is_null($this->_value) || $this->_value === '') {
  220. } else if ($this->_dataType != PHPExcel_Cell_DataType::TYPE_FORMULA) {
  221. return $this->_value;
  222. } else {
  223. return PHPExcel_Calculation::getInstance()->calculate($this);
  224. }
  225. }
  226. /**
  227. * Set calculated value (used for caching)
  228. *
  229. * @param mixed $pValue Value
  230. */
  231. public function setCalculatedValue($pValue = null)
  232. {
  233. if (!is_null($pValue)) {
  234. $this->_calculatedValue = $pValue;
  235. }
  236. }
  237. public function getOldCalculatedValue()
  238. {
  239. return $this->_calculatedValue;
  240. }
  241. /**
  242. * Get cell data type
  243. *
  244. * @return string
  245. */
  246. public function getDataType()
  247. {
  248. return $this->_dataType;
  249. }
  250. /**
  251. * Set cell data type
  252. *
  253. * @param string $pDataType
  254. */
  255. public function setDataType($pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
  256. {
  257. $this->_dataType = $pDataType;
  258. }
  259. /**
  260. * Has Data validation?
  261. *
  262. * @return boolean
  263. */
  264. public function hasDataValidation()
  265. {
  266. return !is_null($this->_dataValidation);
  267. }
  268. /**
  269. * Get Data validation
  270. *
  271. * @return PHPExcel_Cell_DataValidation
  272. */
  273. public function getDataValidation()
  274. {
  275. if (is_null($this->_dataValidation)) {
  276. $this->_dataValidation = new PHPExcel_Cell_DataValidation($this);
  277. }
  278. return $this->_dataValidation;
  279. }
  280. /**
  281. * Set Data validation
  282. *
  283. * @param PHPExcel_Cell_DataValidation $pDataValidation
  284. * @throws Exception
  285. */
  286. public function setDataValidation(PHPExcel_Cell_DataValidation $pDataValidation = null)
  287. {
  288. $this->_dataValidation = $pDataValidation;
  289. $this->_dataValidation->setParent($this);
  290. }
  291. /**
  292. * Has Hyperlink
  293. *
  294. * @return boolean
  295. */
  296. public function hasHyperlink()
  297. {
  298. return !is_null($this->_hyperlink);
  299. }
  300. /**
  301. * Get Hyperlink
  302. *
  303. * @return PHPExcel_Cell_Hyperlink
  304. */
  305. public function getHyperlink()
  306. {
  307. if (is_null($this->_hyperlink)) {
  308. $this->_hyperlink = new PHPExcel_Cell_Hyperlink($this);
  309. }
  310. return $this->_hyperlink;
  311. }
  312. /**
  313. * Set Hyperlink
  314. *
  315. * @param PHPExcel_Cell_Hyperlink $pHyperlink
  316. * @throws Exception
  317. */
  318. public function setHyperlink(PHPExcel_Cell_Hyperlink $pHyperlink = null)
  319. {
  320. $this->_hyperlink = $pHyperlink;
  321. $this->_hyperlink->setParent($this);
  322. }
  323. /**
  324. * Get parent
  325. *
  326. * @return PHPExcel_Worksheet
  327. */
  328. public function getParent() {
  329. return $this->_parent;
  330. }
  331. /**
  332. * Re-bind parent
  333. *
  334. * @param PHPExcel_Worksheet $parent
  335. */
  336. public function rebindParent(PHPExcel_Worksheet $parent) {
  337. $this->_parent = $parent;
  338. }
  339. /**
  340. * Is cell in a specific range?
  341. *
  342. * @param string $pRange Cell range (e.g. A1:A1)
  343. * @return boolean
  344. */
  345. public function isInRange($pRange = 'A1:A1')
  346. {
  347. // Uppercase coordinate
  348. $pRange = strtoupper($pRange);
  349. // Extract range
  350. $rangeA = '';
  351. $rangeB = '';
  352. if (strpos($pRange, ':') === false) {
  353. $rangeA = $pRange;
  354. $rangeB = $pRange;
  355. } else {
  356. list($rangeA, $rangeB) = explode(':', $pRange);
  357. }
  358. // Calculate range outer borders
  359. $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
  360. $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB);
  361. // Translate column into index
  362. $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1;
  363. $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1;
  364. // Translate properties
  365. $myColumn = PHPExcel_Cell::columnIndexFromString($this->getColumn()) - 1;
  366. $myRow = $this->getRow();
  367. // Verify if cell is in range
  368. return (
  369. ($rangeStart[0] <= $myColumn && $rangeEnd[0] >= $myColumn) &&
  370. ($rangeStart[1] <= $myRow && $rangeEnd[1] >= $myRow)
  371. );
  372. }
  373. /**
  374. * Coordinate from string
  375. *
  376. * @param string $pCoordinateString
  377. * @return array Array containing column and row (indexes 0 and 1)
  378. * @throws Exception
  379. */
  380. public static function coordinateFromString($pCoordinateString = 'A1')
  381. {
  382. if (strpos($pCoordinateString,':') !== false) {
  383. throw new Exception('Cell coordinate string can not be a range of cells.');
  384. } else if ($pCoordinateString == '') {
  385. throw new Exception('Cell coordinate can not be zero-length string.');
  386. } else {
  387. // Column
  388. $column = '';
  389. // Row
  390. $row = '';
  391. // Convert a cell reference
  392. if (preg_match("/([$]?[A-Z]+)([$]?\d+)/", $pCoordinateString, $matches)) {
  393. list(, $column, $row) = $matches;
  394. }
  395. // Return array
  396. return array($column, $row);
  397. }
  398. }
  399. /**
  400. * Make string coordinate absolute
  401. *
  402. * @param string $pCoordinateString
  403. * @return string Absolute coordinate
  404. * @throws Exception
  405. */
  406. public static function absoluteCoordinate($pCoordinateString = 'A1')
  407. {
  408. if (strpos($pCoordinateString,':') === false && strpos($pCoordinateString,',') === false) {
  409. // Return value
  410. $returnValue = '';
  411. // Create absolute coordinate
  412. list($column, $row) = PHPExcel_Cell::coordinateFromString($pCoordinateString);
  413. $returnValue = '$' . $column . '$' . $row;
  414. // Return
  415. return $returnValue;
  416. } else {
  417. throw new Exception("Coordinate string should not be a cell range.");
  418. }
  419. }
  420. /**
  421. * Split range into coordinate strings
  422. *
  423. * @param string $pRange
  424. * @return array Array containg one or more arrays containing one or two coordinate strings
  425. */
  426. public static function splitRange($pRange = 'A1:A1')
  427. {
  428. $exploded = explode(',', $pRange);
  429. for ($i = 0; $i < count($exploded); $i++) {
  430. $exploded[$i] = explode(':', $exploded[$i]);
  431. }
  432. return $exploded;
  433. }
  434. /**
  435. * Build range from coordinate strings
  436. *
  437. * @param array $pRange Array containg one or more arrays containing one or two coordinate strings
  438. * @return string String representation of $pRange
  439. * @throws Exception
  440. */
  441. public static function buildRange($pRange)
  442. {
  443. // Verify range
  444. if (!is_array($pRange) || count($pRange) == 0 || !is_array($pRange[0])) {
  445. throw new Exception('Range does not contain any information.');
  446. }
  447. // Build range
  448. $imploded = array();
  449. for ($i = 0; $i < count($pRange); $i++) {
  450. $pRange[$i] = implode(':', $pRange[$i]);
  451. }
  452. $imploded = implode(',', $pRange);
  453. return $imploded;
  454. }
  455. /**
  456. * Calculate range dimension
  457. *
  458. * @param string $pRange Cell range (e.g. A1:A1)
  459. * @return array Range dimension (width, height)
  460. */
  461. public static function rangeDimension($pRange = 'A1:A1')
  462. {
  463. // Uppercase coordinate
  464. $pRange = strtoupper($pRange);
  465. // Extract range
  466. $rangeA = '';
  467. $rangeB = '';
  468. if (strpos($pRange, ':') === false) {
  469. $rangeA = $pRange;
  470. $rangeB = $pRange;
  471. } else {
  472. list($rangeA, $rangeB) = explode(':', $pRange);
  473. }
  474. // Calculate range outer borders
  475. $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
  476. $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB);
  477. // Translate column into index
  478. $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]);
  479. $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]);
  480. return array( ($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1) );
  481. }
  482. /**
  483. * Column index from string
  484. *
  485. * @param string $pString
  486. * @return int Column index (base 1 !!!)
  487. * @throws Exception
  488. */
  489. public static function columnIndexFromString($pString = 'A')
  490. {
  491. // Convert to uppercase
  492. $pString = strtoupper($pString);
  493. $strLen = strlen($pString);
  494. // Convert column to integer
  495. if ($strLen == 1) {
  496. return (ord($pString{0}) - 64);
  497. } elseif ($strLen == 2) {
  498. return $result = ((1 + (ord($pString{0}) - 65)) * 26) + (ord($pString{1}) - 64);
  499. } elseif ($strLen == 3) {
  500. return ((1 + (ord($pString{0}) - 65)) * 676) + ((1 + (ord($pString{1}) - 65)) * 26) + (ord($pString{2}) - 64);
  501. } else {
  502. throw new Exception("Column string index can not be " . ($strLen != 0 ? "longer than 3 characters" : "empty") . ".");
  503. }
  504. }
  505. /**
  506. * String from columnindex
  507. *
  508. * @param int $pColumnIndex Column index (base 0 !!!)
  509. * @return string
  510. */
  511. public static function stringFromColumnIndex($pColumnIndex = 0)
  512. {
  513. // Determine column string
  514. if ($pColumnIndex < 26) {
  515. return chr(65 + $pColumnIndex);
  516. }
  517. return PHPExcel_Cell::stringFromColumnIndex((int)($pColumnIndex / 26) -1).chr(65 + $pColumnIndex%26) ;
  518. }
  519. /**
  520. * Extract all cell references in range
  521. *
  522. * @param string $pRange Range (e.g. A1 or A1:A10 or A1:A10 A100:A1000)
  523. * @return array Array containing single cell references
  524. */
  525. public static function extractAllCellReferencesInRange($pRange = 'A1') {
  526. // Returnvalue
  527. $returnValue = array();
  528. // Explode spaces
  529. $aExplodeSpaces = explode(' ', str_replace('$', '', strtoupper($pRange)));
  530. foreach ($aExplodeSpaces as $explodedSpaces) {
  531. // Single cell?
  532. if (strpos($explodedSpaces,':') === false && strpos($explodedSpaces,',') === false) {
  533. $col = 'A';
  534. $row = 1;
  535. list($col, $row) = PHPExcel_Cell::coordinateFromString($explodedSpaces);
  536. if (strlen($col) <= 2) {
  537. $returnValue[] = $explodedSpaces;
  538. }
  539. continue;
  540. }
  541. // Range...
  542. $range = PHPExcel_Cell::splitRange($explodedSpaces);
  543. for ($i = 0; $i < count($range); $i++) {
  544. // Single cell?
  545. if (count($range[$i]) == 1) {
  546. $col = 'A';
  547. $row = 1;
  548. list($col, $row) = PHPExcel_Cell::coordinateFromString($range[$i]);
  549. if (strlen($col) <= 2) {
  550. $returnValue[] = $explodedSpaces;
  551. }
  552. }
  553. // Range...
  554. $rangeStart = $rangeEnd = '';
  555. $startingCol = $startingRow = $endingCol = $endingRow = 0;
  556. list($rangeStart, $rangeEnd) = $range[$i];
  557. list($startingCol, $startingRow) = PHPExcel_Cell::coordinateFromString($rangeStart);
  558. list($endingCol, $endingRow) = PHPExcel_Cell::coordinateFromString($rangeEnd);
  559. // Conversions...
  560. $startingCol = PHPExcel_Cell::columnIndexFromString($startingCol);
  561. $endingCol = PHPExcel_Cell::columnIndexFromString($endingCol);
  562. // Current data
  563. $currentCol = --$startingCol;
  564. $currentRow = $startingRow;
  565. // Loop cells
  566. while ($currentCol < $endingCol) {
  567. $loopColumn = PHPExcel_Cell::stringFromColumnIndex($currentCol);
  568. while ($currentRow <= $endingRow) {
  569. $returnValue[] = $loopColumn.$currentRow;
  570. ++$currentRow;
  571. }
  572. ++$currentCol;
  573. $currentRow = $startingRow;
  574. }
  575. }
  576. }
  577. // Return value
  578. return $returnValue;
  579. }
  580. /**
  581. * Compare 2 cells
  582. *
  583. * @param PHPExcel_Cell $a Cell a
  584. * @param PHPExcel_Cell $a Cell b
  585. * @return int Result of comparison (always -1 or 1, never zero!)
  586. */
  587. public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b)
  588. {
  589. if ($a->_row < $b->_row) {
  590. return -1;
  591. } elseif ($a->_row > $b->_row) {
  592. return 1;
  593. } elseif (PHPExcel_Cell::columnIndexFromString($a->_column) < PHPExcel_Cell::columnIndexFromString($b->_column)) {
  594. return -1;
  595. } else {
  596. return 1;
  597. }
  598. }
  599. /**
  600. * Get value binder to use
  601. *
  602. * @return PHPExcel_Cell_IValueBinder
  603. */
  604. public static function getValueBinder() {
  605. return self::$_valueBinder;
  606. }
  607. /**
  608. * Set value binder to use
  609. *
  610. * @param PHPExcel_Cell_IValueBinder $binder
  611. * @throws Exception
  612. */
  613. public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = null) {
  614. if (is_null($binder)) {
  615. throw new Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly.");
  616. }
  617. self::$_valueBinder = $binder;
  618. }
  619. /**
  620. * Implement PHP __clone to create a deep clone, not just a shallow copy.
  621. */
  622. public function __clone() {
  623. $vars = get_object_vars($this);
  624. foreach ($vars as $key => $value) {
  625. if (is_object($value)) {
  626. $this->$key = clone $value;
  627. } else {
  628. $this->$key = $value;
  629. }
  630. }
  631. }
  632. }