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

/branches/wi6857-memory/Classes/PHPExcel/Cell.php

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