From cd30b519041ffbbbdcbf66a3116bc41ed0ac60cc Mon Sep 17 00:00:00 2001 From: Dieter Adriaenssens Date: Sun, 2 May 2010 20:20:06 +0200 Subject: [PATCH 1/6] upgrade to PHPExcel 1.7.0 --- .../PHPExcel/Shared/Escher/DgContainer.php | 2 +- .../Escher/DgContainer/SpgrContainer.php | 2 +- .../DgContainer/SpgrContainer/SpContainer.php | 2 +- .../PHPExcel/Shared/Escher/DggContainer.php | 2 +- .../Escher/DggContainer/BstoreContainer.php | 2 +- .../DggContainer/BstoreContainer/BSE.php | 2 +- .../DggContainer/BstoreContainer/BSE/Blip.php | 2 +- .../Shared/JAMA/CholeskyDecomposition.php | 274 +- .../Shared/JAMA/EigenvalueDecomposition.php | 1611 +++++----- .../PHPExcel/Shared/JAMA/LUDecomposition.php | 461 +-- .../PHPExcel/PHPExcel/Shared/JAMA/Matrix.php | 2678 +++++++++-------- .../PHPExcel/Shared/JAMA/QRDecomposition.php | 407 +-- .../JAMA/SingularValueDecomposition.php | 973 +++--- .../PHPExcel/Shared/JAMA/utils/Error.php | 130 +- .../PHPExcel/Shared/JAMA/utils/Maths.php | 69 +- 15 files changed, 3398 insertions(+), 3219 deletions(-) diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php index 588cae727..1084d94f6 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php index 3114f9c62..846b56990 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php index e05188b74..481e7db55 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php index 7b1741c82..cdbdde01f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php index 4c26bb384..4209b424c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php index ae0f246d2..e472b218c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php index 41d095657..d835a0687 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.6.7, 2009-04-22 + * @version 1.7.0, 2009-08-10 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php index b401b8491..9d064f9e6 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php @@ -1,133 +1,149 @@ L = $A->getArray(); - $this->m = $A->getRowDimension(); - - for( $i = 0; $i < $this->m; $i++ ) { - for( $j = $i; $j < $this->m; $j++ ) { - for( $sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; $k-- ) - $sum -= $this->L[$i][$k] * $this->L[$j][$k]; - if( $i == $j ) { - if( $sum >= 0 ) { - $this->L[$i][$i] = sqrt( $sum ); - } else { - $this->isspd = false; - } - } else { - if( $this->L[$i][$i] != 0 ) - $this->L[$j][$i] = $sum / $this->L[$i][$i]; - } - } - - for ($k = $i+1; $k < $this->m; $k++) - $this->L[$i][$k] = 0.0; - } - } else { - trigger_error(ArgumentTypeException, ERROR); - } - } - - /** - * Is the matrix symmetric and positive definite? - * @return boolean - */ - function isSPD () { - return $this->isspd; - } - - /** - * getL - * Return triangular factor. - * @return Matrix Lower triangular matrix - */ - function getL () { - return new Matrix($this->L); - } - - /** - * Solve A*X = B - * @param $B Row-equal matrix - * @return Matrix L * L' * X = B - */ - function solve ( $B = null ) { - if( is_a($B, 'Matrix') ) { - if ($B->getRowDimension() == $this->m) { - if ($this->isspd) { - $X = $B->getArrayCopy(); - $nx = $B->getColumnDimension(); - - for ($k = 0; $k < $this->m; $k++) { - for ($i = $k + 1; $i < $this->m; $i++) - for ($j = 0; $j < $nx; $j++) - $X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k]; - - for ($j = 0; $j < $nx; $j++) - $X[$k][$j] /= $this->L[$k][$k]; - } - - for ($k = $this->m - 1; $k >= 0; $k--) { - for ($j = 0; $j < $nx; $j++) - $X[$k][$j] /= $this->L[$k][$k]; - - for ($i = 0; $i < $k; $i++) - for ($j = 0; $j < $nx; $j++) - $X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i]; - } - - return new Matrix($X, $this->m, $nx); - } else { - trigger_error(MatrixSPDException, ERROR); - } - } else { - trigger_error(MatrixDimensionException, ERROR); - } - } else { - trigger_error(ArgumentTypeException, ERROR); - } - } -} + /** + * Decomposition storage + * @var array + * @access private + */ + private $L = array(); + + /** + * Matrix row and column dimension + * @var int + * @access private + */ + private $m; + + /** + * Symmetric positive definite flag + * @var boolean + * @access private + */ + private $isspd = true; + + + /** + * CholeskyDecomposition + * + * Class constructor - decomposes symmetric positive definite matrix + * @param mixed Matrix square symmetric positive definite matrix + */ + public function __construct($A = null) { + if ($A instanceof Matrix) { + $this->L = $A->getArray(); + $this->m = $A->getRowDimension(); + + for($i = 0; $i < $this->m; ++$i) { + for($j = $i; $j < $this->m; ++$j) { + for($sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; --$k) { + $sum -= $this->L[$i][$k] * $this->L[$j][$k]; + } + if ($i == $j) { + if ($sum >= 0) { + $this->L[$i][$i] = sqrt($sum); + } else { + $this->isspd = false; + } + } else { + if ($this->L[$i][$i] != 0) { + $this->L[$j][$i] = $sum / $this->L[$i][$i]; + } + } + } + + for ($k = $i+1; $k < $this->m; ++$k) { + $this->L[$i][$k] = 0.0; + } + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function __construct() + + + /** + * Is the matrix symmetric and positive definite? + * + * @return boolean + */ + public function isSPD() { + return $this->isspd; + } // function isSPD() + + + /** + * getL + * + * Return triangular factor. + * @return Matrix Lower triangular matrix + */ + public function getL() { + return new Matrix($this->L); + } // function getL() + + + /** + * Solve A*X = B + * + * @param $B Row-equal matrix + * @return Matrix L * L' * X = B + */ + public function solve($B = null) { + if ($B instanceof Matrix) { + if ($B->getRowDimension() == $this->m) { + if ($this->isspd) { + $X = $B->getArrayCopy(); + $nx = $B->getColumnDimension(); + + for ($k = 0; $k < $this->m; ++$k) { + for ($i = $k + 1; $i < $this->m; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k]; + } + } + for ($j = 0; $j < $nx; ++$j) { + $X[$k][$j] /= $this->L[$k][$k]; + } + } + + for ($k = $this->m - 1; $k >= 0; --$k) { + for ($j = 0; $j < $nx; ++$j) { + $X[$k][$j] /= $this->L[$k][$k]; + } + for ($i = 0; $i < $k; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i]; + } + } + } + + return new Matrix($X, $this->m, $nx); + } else { + throw new Exception(JAMAError(MatrixSPDException)); + } + } else { + throw new Exception(JAMAError(MatrixDimensionException)); + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function solve() + +} // class CholeskyDecomposition diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php index a010884b7..2a696d00f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php @@ -1,789 +1,862 @@ d = $this->V[$this->n-1]; - // Householder reduction to tridiagonal form. - for ($i = $this->n-1; $i > 0; $i--) { - $i_ = $i -1; - // Scale to avoid under/overflow. - $h = $scale = 0.0; - $scale += array_sum(array_map(abs, $this->d)); - if ($scale == 0.0) { - $this->e[$i] = $this->d[$i_]; - $this->d = array_slice($this->V[$i_], 0, $i_); - for ($j = 0; $j < $i; $j++) { - $this->V[$j][$i] = $this->V[$i][$j] = 0.0; - } - } else { - // Generate Householder vector. - for ($k = 0; $k < $i; $k++) { - $this->d[$k] /= $scale; - $h += pow($this->d[$k], 2); - } - $f = $this->d[$i_]; - $g = sqrt($h); - if ($f > 0) - $g = -$g; - $this->e[$i] = $scale * $g; - $h = $h - $f * $g; - $this->d[$i_] = $f - $g; - for ($j = 0; $j < $i; $j++) - $this->e[$j] = 0.0; - // Apply similarity transformation to remaining columns. - for ($j = 0; $j < $i; $j++) { - $f = $this->d[$j]; - $this->V[$j][$i] = $f; - $g = $this->e[$j] + $this->V[$j][$j] * $f; - for ($k = $j+1; $k <= $i_; $k++) { - $g += $this->V[$k][$j] * $this->d[$k]; - $this->e[$k] += $this->V[$k][$j] * $f; - } - $this->e[$j] = $g; - } - $f = 0.0; - for ($j = 0; $j < $i; $j++) { - $this->e[$j] /= $h; - $f += $this->e[$j] * $this->d[$j]; - } - $hh = $f / (2 * $h); - for ($j=0; $j < $i; $j++) - $this->e[$j] -= $hh * $this->d[$j]; - for ($j = 0; $j < $i; $j++) { - $f = $this->d[$j]; - $g = $this->e[$j]; - for ($k = $j; $k <= $i_; $k++) - $this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]); - $this->d[$j] = $this->V[$i-1][$j]; - $this->V[$i][$j] = 0.0; - } - } - $this->d[$i] = $h; - } - // Accumulate transformations. - for ($i = 0; $i < $this->n-1; $i++) { - $this->V[$this->n-1][$i] = $this->V[$i][$i]; - $this->V[$i][$i] = 1.0; - $h = $this->d[$i+1]; - if ($h != 0.0) { - for ($k = 0; $k <= $i; $k++) - $this->d[$k] = $this->V[$k][$i+1] / $h; - for ($j = 0; $j <= $i; $j++) { - $g = 0.0; - for ($k = 0; $k <= $i; $k++) - $g += $this->V[$k][$i+1] * $this->V[$k][$j]; - for ($k = 0; $k <= $i; $k++) - $this->V[$k][$j] -= $g * $this->d[$k]; - } - } - for ($k = 0; $k <= $i; $k++) - $this->V[$k][$i+1] = 0.0; - } + /** + * Symmetric Householder reduction to tridiagonal form. + * + * @access private + */ + private function tred2 () { + // This is derived from the Algol procedures tred2 by + // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for + // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutine in EISPACK. + $this->d = $this->V[$this->n-1]; + // Householder reduction to tridiagonal form. + for ($i = $this->n-1; $i > 0; --$i) { + $i_ = $i -1; + // Scale to avoid under/overflow. + $h = $scale = 0.0; + $scale += array_sum(array_map(abs, $this->d)); + if ($scale == 0.0) { + $this->e[$i] = $this->d[$i_]; + $this->d = array_slice($this->V[$i_], 0, $i_); + for ($j = 0; $j < $i; ++$j) { + $this->V[$j][$i] = $this->V[$i][$j] = 0.0; + } + } else { + // Generate Householder vector. + for ($k = 0; $k < $i; ++$k) { + $this->d[$k] /= $scale; + $h += pow($this->d[$k], 2); + } + $f = $this->d[$i_]; + $g = sqrt($h); + if ($f > 0) { + $g = -$g; + } + $this->e[$i] = $scale * $g; + $h = $h - $f * $g; + $this->d[$i_] = $f - $g; + for ($j = 0; $j < $i; ++$j) { + $this->e[$j] = 0.0; + } + // Apply similarity transformation to remaining columns. + for ($j = 0; $j < $i; ++$j) { + $f = $this->d[$j]; + $this->V[$j][$i] = $f; + $g = $this->e[$j] + $this->V[$j][$j] * $f; + for ($k = $j+1; $k <= $i_; ++$k) { + $g += $this->V[$k][$j] * $this->d[$k]; + $this->e[$k] += $this->V[$k][$j] * $f; + } + $this->e[$j] = $g; + } + $f = 0.0; + for ($j = 0; $j < $i; ++$j) { + $this->e[$j] /= $h; + $f += $this->e[$j] * $this->d[$j]; + } + $hh = $f / (2 * $h); + for ($j=0; $j < $i; ++$j) { + $this->e[$j] -= $hh * $this->d[$j]; + } + for ($j = 0; $j < $i; ++$j) { + $f = $this->d[$j]; + $g = $this->e[$j]; + for ($k = $j; $k <= $i_; ++$k) { + $this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]); + } + $this->d[$j] = $this->V[$i-1][$j]; + $this->V[$i][$j] = 0.0; + } + } + $this->d[$i] = $h; + } - $this->d = $this->V[$this->n-1]; - $this->V[$this->n-1] = array_fill(0, $j, 0.0); - $this->V[$this->n-1][$this->n-1] = 1.0; - $this->e[0] = 0.0; - } + // Accumulate transformations. + for ($i = 0; $i < $this->n-1; ++$i) { + $this->V[$this->n-1][$i] = $this->V[$i][$i]; + $this->V[$i][$i] = 1.0; + $h = $this->d[$i+1]; + if ($h != 0.0) { + for ($k = 0; $k <= $i; ++$k) { + $this->d[$k] = $this->V[$k][$i+1] / $h; + } + for ($j = 0; $j <= $i; ++$j) { + $g = 0.0; + for ($k = 0; $k <= $i; ++$k) { + $g += $this->V[$k][$i+1] * $this->V[$k][$j]; + } + for ($k = 0; $k <= $i; ++$k) { + $this->V[$k][$j] -= $g * $this->d[$k]; + } + } + } + for ($k = 0; $k <= $i; ++$k) { + $this->V[$k][$i+1] = 0.0; + } + } - /** - * Symmetric tridiagonal QL algorithm. - * - * This is derived from the Algol procedures tql2, by - * Bowdler, Martin, Reinsch, and Wilkinson, Handbook for - * Auto. Comp., Vol.ii-Linear Algebra, and the corresponding - * Fortran subroutine in EISPACK. - * - * @access private - */ - function tql2 () { - for ($i = 1; $i < $this->n; $i++) - $this->e[$i-1] = $this->e[$i]; - $this->e[$this->n-1] = 0.0; - $f = 0.0; - $tst1 = 0.0; - $eps = pow(2.0,-52.0); - for ($l = 0; $l < $this->n; $l++) { - // Find small subdiagonal element - $tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l])); - $m = $l; - while ($m < $this->n) { - if (abs($this->e[$m]) <= $eps * $tst1) - break; - $m++; - } - // If m == l, $this->d[l] is an eigenvalue, - // otherwise, iterate. - if ($m > $l) { - $iter = 0; - do { - // Could check iteration count here. - $iter += 1; - // Compute implicit shift - $g = $this->d[$l]; - $p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]); - $r = hypo($p, 1.0); - if ($p < 0) - $r *= -1; - $this->d[$l] = $this->e[$l] / ($p + $r); - $this->d[$l+1] = $this->e[$l] * ($p + $r); - $dl1 = $this->d[$l+1]; - $h = $g - $this->d[$l]; - for ($i = $l + 2; $i < $this->n; $i++) - $this->d[$i] -= $h; - $f += $h; - // Implicit QL transformation. - $p = $this->d[$m]; - $c = 1.0; - $c2 = $c3 = $c; - $el1 = $this->e[$l + 1]; - $s = $s2 = 0.0; - for ($i = $m-1; $i >= $l; $i--) { - $c3 = $c2; - $c2 = $c; - $s2 = $s; - $g = $c * $this->e[$i]; - $h = $c * $p; - $r = hypo($p, $this->e[$i]); - $this->e[$i+1] = $s * $r; - $s = $this->e[$i] / $r; - $c = $p / $r; - $p = $c * $this->d[$i] - $s * $g; - $this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]); - // Accumulate transformation. - for ($k = 0; $k < $this->n; $k++) { - $h = $this->V[$k][$i+1]; - $this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h; - $this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h; - } - } - $p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1; - $this->e[$l] = $s * $p; - $this->d[$l] = $c * $p; - // Check for convergence. - } while (abs($this->e[$l]) > $eps * $tst1); - } - $this->d[$l] = $this->d[$l] + $f; - $this->e[$l] = 0.0; - } - // Sort eigenvalues and corresponding vectors. - for ($i = 0; $i < $this->n - 1; $i++) { - $k = $i; - $p = $this->d[$i]; - for ($j = $i+1; $j < $this->n; $j++) { - if ($this->d[$j] < $p) { - $k = $j; - $p = $this->d[$j]; - } - } - if ($k != $i) { - $this->d[$k] = $this->d[$i]; - $this->d[$i] = $p; - for ($j = 0; $j < $this->n; $j++) { - $p = $this->V[$j][$i]; - $this->V[$j][$i] = $this->V[$j][$k]; - $this->V[$j][$k] = $p; - } - } - } - } + $this->d = $this->V[$this->n-1]; + $this->V[$this->n-1] = array_fill(0, $j, 0.0); + $this->V[$this->n-1][$this->n-1] = 1.0; + $this->e[0] = 0.0; + } - /** - * Nonsymmetric reduction to Hessenberg form. - * - * This is derived from the Algol procedures orthes and ortran, - * by Martin and Wilkinson, Handbook for Auto. Comp., - * Vol.ii-Linear Algebra, and the corresponding - * Fortran subroutines in EISPACK. - * - * @access private - */ - function orthes () { - $low = 0; - $high = $this->n-1; - for ($m = $low+1; $m <= $high-1; $m++) { - // Scale column. - $scale = 0.0; - for ($i = $m; $i <= $high; $i++) - $scale = $scale + abs($this->H[$i][$m-1]); - if ($scale != 0.0) { - // Compute Householder transformation. - $h = 0.0; - for ($i = $high; $i >= $m; $i--) { - $this->ort[$i] = $this->H[$i][$m-1]/$scale; - $h += $this->ort[$i] * $this->ort[$i]; - } - $g = sqrt($h); - if ($this->ort[$m] > 0) - $g *= -1; - $h -= $this->ort[$m] * $g; - $this->ort[$m] -= $g; - // Apply Householder similarity transformation - // H = (I-u*u'/h)*H*(I-u*u')/h) - for ($j = $m; $j < $this->n; $j++) { - $f = 0.0; - for ($i = $high; $i >= $m; $i--) - $f += $this->ort[$i] * $this->H[$i][$j]; - $f /= $h; - for ($i = $m; $i <= $high; $i++) - $this->H[$i][$j] -= $f * $this->ort[$i]; - } - for ($i = 0; $i <= $high; $i++) { - $f = 0.0; - for ($j = $high; $j >= $m; $j--) - $f += $this->ort[$j] * $this->H[$i][$j]; - $f = $f/$h; - for ($j = $m; $j <= $high; $j++) - $this->H[$i][$j] -= $f * $this->ort[$j]; - } - $this->ort[$m] = $scale * $this->ort[$m]; - $this->H[$m][$m-1] = $scale * $g; - } - } - // Accumulate transformations (Algol's ortran). - for ($i = 0; $i < $this->n; $i++) - for ($j = 0; $j < $this->n; $j++) - $this->V[$i][$j] = ($i == $j ? 1.0 : 0.0); - for ($m = $high-1; $m >= $low+1; $m--) { - if ($this->H[$m][$m-1] != 0.0) { - for ($i = $m+1; $i <= $high; $i++) - $this->ort[$i] = $this->H[$i][$m-1]; - for ($j = $m; $j <= $high; $j++) { - $g = 0.0; - for ($i = $m; $i <= $high; $i++) - $g += $this->ort[$i] * $this->V[$i][$j]; - // Double division avoids possible underflow - $g = ($g / $this->ort[$m]) / $this->H[$m][$m-1]; - for ($i = $m; $i <= $high; $i++) - $this->V[$i][$j] += $g * $this->ort[$i]; - } - } - } - } - /** - * Performs complex division. - * @access private - */ - function cdiv($xr, $xi, $yr, $yi) { - if (abs($yr) > abs($yi)) { - $r = $yi / $yr; - $d = $yr + $r * $yi; - $this->cdivr = ($xr + $r * $xi) / $d; - $this->cdivi = ($xi - $r * $xr) / $d; - } else { - $r = $yr / $yi; - $d = $yi + $r * $yr; - $this->cdivr = ($r * $xr + $xi) / $d; - $this->cdivi = ($r * $xi - $xr) / $d; - } - } - - /** - * Nonsymmetric reduction from Hessenberg to real Schur form. - * - * Code is derived from the Algol procedure hqr2, - * by Martin and Wilkinson, Handbook for Auto. Comp., - * Vol.ii-Linear Algebra, and the corresponding - * Fortran subroutine in EISPACK. - * - * @access private - */ - function hqr2 () { - // Initialize - $nn = $this->n; - $n = $nn - 1; - $low = 0; - $high = $nn - 1; - $eps = pow(2.0, -52.0); - $exshift = 0.0; - $p = $q = $r = $s = $z = 0; - // Store roots isolated by balanc and compute matrix norm - $norm = 0.0; - for ($i = 0; $i < $nn; $i++) { - if (($i < $low) OR ($i > $high)) { - $this->d[$i] = $this->H[$i][$i]; - $this->e[$i] = 0.0; - } - for ($j = max($i-1, 0); $j < $nn; $j++) - $norm = $norm + abs($this->H[$i][$j]); - } - // Outer loop over eigenvalue index - $iter = 0; - while ($n >= $low) { - // Look for single small sub-diagonal element - $l = $n; - while ($l > $low) { - $s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]); - if ($s == 0.0) - $s = $norm; - if (abs($this->H[$l][$l-1]) < $eps * $s) - break; - $l--; - } - // Check for convergence - // One root found - if ($l == $n) { - $this->H[$n][$n] = $this->H[$n][$n] + $exshift; - $this->d[$n] = $this->H[$n][$n]; - $this->e[$n] = 0.0; - $n--; - $iter = 0; - // Two roots found - } else if ($l == $n-1) { - $w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; - $p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0; - $q = $p * $p + $w; - $z = sqrt(abs($q)); - $this->H[$n][$n] = $this->H[$n][$n] + $exshift; - $this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift; - $x = $this->H[$n][$n]; - // Real pair - if ($q >= 0) { - if ($p >= 0) - $z = $p + $z; - else - $z = $p - $z; - $this->d[$n-1] = $x + $z; - $this->d[$n] = $this->d[$n-1]; - if ($z != 0.0) - $this->d[$n] = $x - $w / $z; - $this->e[$n-1] = 0.0; - $this->e[$n] = 0.0; - $x = $this->H[$n][$n-1]; - $s = abs($x) + abs($z); - $p = $x / $s; - $q = $z / $s; - $r = sqrt($p * $p + $q * $q); - $p = $p / $r; - $q = $q / $r; - // Row modification - for ($j = $n-1; $j < $nn; $j++) { - $z = $this->H[$n-1][$j]; - $this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j]; - $this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z; - } - // Column modification - for ($i = 0; $i <= n; $i++) { - $z = $this->H[$i][$n-1]; - $this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n]; - $this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z; - } - // Accumulate transformations - for ($i = $low; $i <= $high; $i++) { - $z = $this->V[$i][$n-1]; - $this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n]; - $this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z; - } - // Complex pair - } else { - $this->d[$n-1] = $x + $p; - $this->d[$n] = $x + $p; - $this->e[$n-1] = $z; - $this->e[$n] = -$z; - } - $n = $n - 2; - $iter = 0; - // No convergence yet - } else { - // Form shift - $x = $this->H[$n][$n]; - $y = 0.0; - $w = 0.0; - if ($l < $n) { - $y = $this->H[$n-1][$n-1]; - $w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; - } - // Wilkinson's original ad hoc shift - if ($iter == 10) { - $exshift += $x; - for ($i = $low; $i <= $n; $i++) - $this->H[$i][$i] -= $x; - $s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]); - $x = $y = 0.75 * $s; - $w = -0.4375 * $s * $s; - } - // MATLAB's new ad hoc shift - if ($iter == 30) { - $s = ($y - $x) / 2.0; - $s = $s * $s + $w; - if ($s > 0) { - $s = sqrt($s); - if ($y < $x) - $s = -$s; - $s = $x - $w / (($y - $x) / 2.0 + $s); - for ($i = $low; $i <= $n; $i++) - $this->H[$i][$i] -= $s; - $exshift += $s; - $x = $y = $w = 0.964; - } - } - // Could check iteration count here. - $iter = $iter + 1; - // Look for two consecutive small sub-diagonal elements - $m = $n - 2; - while ($m >= $l) { - $z = $this->H[$m][$m]; - $r = $x - $z; - $s = $y - $z; - $p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1]; - $q = $this->H[$m+1][$m+1] - $z - $r - $s; - $r = $this->H[$m+2][$m+1]; - $s = abs($p) + abs($q) + abs($r); - $p = $p / $s; - $q = $q / $s; - $r = $r / $s; - if ($m == $l) - break; - if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) < $eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) - break; - $m--; - } - for ($i = $m + 2; $i <= $n; $i++) { - $this->H[$i][$i-2] = 0.0; - if ($i > $m+2) - $this->H[$i][$i-3] = 0.0; - } - // Double QR step involving rows l:n and columns m:n - for ($k = $m; $k <= $n-1; $k++) { - $notlast = ($k != $n-1); - if ($k != $m) { - $p = $this->H[$k][$k-1]; - $q = $this->H[$k+1][$k-1]; - $r = ($notlast ? $this->H[$k+2][$k-1] : 0.0); - $x = abs($p) + abs($q) + abs($r); - if ($x != 0.0) { - $p = $p / $x; - $q = $q / $x; - $r = $r / $x; - } - } - if ($x == 0.0) - break; - $s = sqrt($p * $p + $q * $q + $r * $r); - if ($p < 0) - $s = -$s; - if ($s != 0) { - if ($k != $m) - $this->H[$k][$k-1] = -$s * $x; - else if ($l != $m) - $this->H[$k][$k-1] = -$this->H[$k][$k-1]; - $p = $p + $s; - $x = $p / $s; - $y = $q / $s; - $z = $r / $s; - $q = $q / $p; - $r = $r / $p; - // Row modification - for ($j = $k; $j < $nn; $j++) { - $p = $this->H[$k][$j] + $q * $this->H[$k+1][$j]; - if ($notlast) { - $p = $p + $r * $this->H[$k+2][$j]; - $this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z; - } - $this->H[$k][$j] = $this->H[$k][$j] - $p * $x; - $this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y; - } - // Column modification - for ($i = 0; $i <= min($n, $k+3); $i++) { - $p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1]; - if ($notlast) { - $p = $p + $z * $this->H[$i][$k+2]; - $this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r; - } - $this->H[$i][$k] = $this->H[$i][$k] - $p; - $this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q; - } - // Accumulate transformations - for ($i = $low; $i <= $high; $i++) { - $p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1]; - if ($notlast) { - $p = $p + $z * $this->V[$i][$k+2]; - $this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r; - } - $this->V[$i][$k] = $this->V[$i][$k] - $p; - $this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q; - } - } // ($s != 0) - } // k loop - } // check convergence - } // while ($n >= $low) - // Backsubstitute to find vectors of upper triangular form - if ($norm == 0.0) - return; - for ($n = $nn-1; $n >= 0; $n--) { - $p = $this->d[$n]; - $q = $this->e[$n]; - // Real vector - if ($q == 0) { - $l = $n; - $this->H[$n][$n] = 1.0; - for ($i = $n-1; $i >= 0; $i--) { - $w = $this->H[$i][$i] - $p; - $r = 0.0; - for ($j = $l; $j <= $n; $j++) - $r = $r + $this->H[$i][$j] * $this->H[$j][$n]; - if ($this->e[$i] < 0.0) { - $z = $w; - $s = $r; - } else { - $l = $i; - if ($this->e[$i] == 0.0) { - if ($w != 0.0) - $this->H[$i][$n] = -$r / $w; - else - $this->H[$i][$n] = -$r / ($eps * $norm); - // Solve real equations - } else { - $x = $this->H[$i][$i+1]; - $y = $this->H[$i+1][$i]; - $q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i]; - $t = ($x * $s - $z * $r) / $q; - $this->H[$i][$n] = $t; - if (abs($x) > abs($z)) - $this->H[$i+1][$n] = (-$r - $w * $t) / $x; - else - $this->H[$i+1][$n] = (-$s - $y * $t) / $z; - } - // Overflow control - $t = abs($this->H[$i][$n]); - if (($eps * $t) * $t > 1) { - for ($j = $i; $j <= $n; $j++) - $this->H[$j][$n] = $this->H[$j][$n] / $t; - } - } - } - // Complex vector - } else if ($q < 0) { - $l = $n-1; - // Last vector component imaginary so matrix is triangular - if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) { - $this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1]; - $this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1]; - } else { - $this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q); - $this->H[$n-1][$n-1] = $this->cdivr; - $this->H[$n-1][$n] = $this->cdivi; - } - $this->H[$n][$n-1] = 0.0; - $this->H[$n][$n] = 1.0; - for ($i = $n-2; $i >= 0; $i--) { - // double ra,sa,vr,vi; - $ra = 0.0; - $sa = 0.0; - for ($j = $l; $j <= $n; $j++) { - $ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1]; - $sa = $sa + $this->H[$i][$j] * $this->H[$j][$n]; - } - $w = $this->H[$i][$i] - $p; - if ($this->e[$i] < 0.0) { - $z = $w; - $r = $ra; - $s = $sa; - } else { - $l = $i; - if ($this->e[$i] == 0) { - $this->cdiv(-$ra, -$sa, $w, $q); - $this->H[$i][$n-1] = $this->cdivr; - $this->H[$i][$n] = $this->cdivi; - } else { - // Solve complex equations - $x = $this->H[$i][$i+1]; - $y = $this->H[$i+1][$i]; - $vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q; - $vi = ($this->d[$i] - $p) * 2.0 * $q; - if ($vr == 0.0 & $vi == 0.0) - $vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z)); - $this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi); - $this->H[$i][$n-1] = $this->cdivr; - $this->H[$i][$n] = $this->cdivi; - if (abs($x) > (abs($z) + abs($q))) { - $this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x; - $this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x; - } else { - $this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q); - $this->H[$i+1][$n-1] = $this->cdivr; - $this->H[$i+1][$n] = $this->cdivi; - } - } - // Overflow control - $t = max(abs($this->H[$i][$n-1]),abs($this->H[$i][$n])); - if (($eps * $t) * $t > 1) { - for ($j = $i; $j <= $n; $j++) { - $this->H[$j][$n-1] = $this->H[$j][$n-1] / $t; - $this->H[$j][$n] = $this->H[$j][$n] / $t; - } - } - } // end else - } // end for - } // end else for complex case - } // end for - // Vectors of isolated roots - for ($i = 0; $i < $nn; $i++) { - if ($i < $low | $i > $high) { - for ($j = $i; $j < $nn; $j++) - $this->V[$i][$j] = $this->H[$i][$j]; - } - } - // Back transformation to get eigenvectors of original matrix - for ($j = $nn-1; $j >= $low; $j--) { - for ($i = $low; $i <= $high; $i++) { - $z = 0.0; - for ($k = $low; $k <= min($j,$high); $k++) - $z = $z + $this->V[$i][$k] * $this->H[$k][$j]; - $this->V[$i][$j] = $z; - } - } - } // end hqr2 - - /** - * Constructor: Check for symmetry, then construct the eigenvalue decomposition - * @access public - * @param A Square matrix - * @return Structure to access D and V. - */ - function EigenvalueDecomposition($Arg) { - $this->A = $Arg->getArray(); - $this->n = $Arg->getColumnDimension(); - $this->V = array(); - $this->d = array(); - $this->e = array(); - $issymmetric = true; - for ($j = 0; ($j < $this->n) & $issymmetric; $j++) - for ($i = 0; ($i < $this->n) & $issymmetric; $i++) - $issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]); - if ($issymmetric) { - $this->V = $this->A; - // Tridiagonalize. - $this->tred2(); - // Diagonalize. - $this->tql2(); - } else { - $this->H = $this->A; - $this->ort = array(); - // Reduce to Hessenberg form. - $this->orthes(); - // Reduce Hessenberg to real Schur form. - $this->hqr2(); - } - } + /** + * Symmetric tridiagonal QL algorithm. + * + * This is derived from the Algol procedures tql2, by + * Bowdler, Martin, Reinsch, and Wilkinson, Handbook for + * Auto. Comp., Vol.ii-Linear Algebra, and the corresponding + * Fortran subroutine in EISPACK. + * + * @access private + */ + private function tql2() { + for ($i = 1; $i < $this->n; ++$i) { + $this->e[$i-1] = $this->e[$i]; + } + $this->e[$this->n-1] = 0.0; + $f = 0.0; + $tst1 = 0.0; + $eps = pow(2.0,-52.0); - /** - * Return the eigenvector matrix - * @access public - * @return V - */ - function getV() { - return new Matrix($this->V, $this->n, $this->n); - } + for ($l = 0; $l < $this->n; ++$l) { + // Find small subdiagonal element + $tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l])); + $m = $l; + while ($m < $this->n) { + if (abs($this->e[$m]) <= $eps * $tst1) + break; + ++$m; + } + // If m == l, $this->d[l] is an eigenvalue, + // otherwise, iterate. + if ($m > $l) { + $iter = 0; + do { + // Could check iteration count here. + $iter += 1; + // Compute implicit shift + $g = $this->d[$l]; + $p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]); + $r = hypo($p, 1.0); + if ($p < 0) + $r *= -1; + $this->d[$l] = $this->e[$l] / ($p + $r); + $this->d[$l+1] = $this->e[$l] * ($p + $r); + $dl1 = $this->d[$l+1]; + $h = $g - $this->d[$l]; + for ($i = $l + 2; $i < $this->n; ++$i) + $this->d[$i] -= $h; + $f += $h; + // Implicit QL transformation. + $p = $this->d[$m]; + $c = 1.0; + $c2 = $c3 = $c; + $el1 = $this->e[$l + 1]; + $s = $s2 = 0.0; + for ($i = $m-1; $i >= $l; --$i) { + $c3 = $c2; + $c2 = $c; + $s2 = $s; + $g = $c * $this->e[$i]; + $h = $c * $p; + $r = hypo($p, $this->e[$i]); + $this->e[$i+1] = $s * $r; + $s = $this->e[$i] / $r; + $c = $p / $r; + $p = $c * $this->d[$i] - $s * $g; + $this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]); + // Accumulate transformation. + for ($k = 0; $k < $this->n; ++$k) { + $h = $this->V[$k][$i+1]; + $this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h; + $this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h; + } + } + $p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1; + $this->e[$l] = $s * $p; + $this->d[$l] = $c * $p; + // Check for convergence. + } while (abs($this->e[$l]) > $eps * $tst1); + } + $this->d[$l] = $this->d[$l] + $f; + $this->e[$l] = 0.0; + } - /** - * Return the real parts of the eigenvalues - * @access public - * @return real(diag(D)) - */ - function getRealEigenvalues() { - return $this->d; - } + // Sort eigenvalues and corresponding vectors. + for ($i = 0; $i < $this->n - 1; ++$i) { + $k = $i; + $p = $this->d[$i]; + for ($j = $i+1; $j < $this->n; ++$j) { + if ($this->d[$j] < $p) { + $k = $j; + $p = $this->d[$j]; + } + } + if ($k != $i) { + $this->d[$k] = $this->d[$i]; + $this->d[$i] = $p; + for ($j = 0; $j < $this->n; ++$j) { + $p = $this->V[$j][$i]; + $this->V[$j][$i] = $this->V[$j][$k]; + $this->V[$j][$k] = $p; + } + } + } + } - /** - * Return the imaginary parts of the eigenvalues - * @access public - * @return imag(diag(D)) - */ - function getImagEigenvalues() { - return $this->e; - } - /** - * Return the block diagonal eigenvalue matrix - * @access public - * @return D - */ - function getD() { - for ($i = 0; $i < $this->n; $i++) { - $D[$i] = array_fill(0, $this->n, 0.0); - $D[$i][$i] = $this->d[$i]; - if ($this->e[$i] == 0) - continue; - $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1; - $D[$i][$o] = $this->e[$i]; - } - return new Matrix($D); - } -} + /** + * Nonsymmetric reduction to Hessenberg form. + * + * This is derived from the Algol procedures orthes and ortran, + * by Martin and Wilkinson, Handbook for Auto. Comp., + * Vol.ii-Linear Algebra, and the corresponding + * Fortran subroutines in EISPACK. + * + * @access private + */ + private function orthes () { + $low = 0; + $high = $this->n-1; + + for ($m = $low+1; $m <= $high-1; ++$m) { + // Scale column. + $scale = 0.0; + for ($i = $m; $i <= $high; ++$i) { + $scale = $scale + abs($this->H[$i][$m-1]); + } + if ($scale != 0.0) { + // Compute Householder transformation. + $h = 0.0; + for ($i = $high; $i >= $m; --$i) { + $this->ort[$i] = $this->H[$i][$m-1] / $scale; + $h += $this->ort[$i] * $this->ort[$i]; + } + $g = sqrt($h); + if ($this->ort[$m] > 0) { + $g *= -1; + } + $h -= $this->ort[$m] * $g; + $this->ort[$m] -= $g; + // Apply Householder similarity transformation + // H = (I -u * u' / h) * H * (I -u * u') / h) + for ($j = $m; $j < $this->n; ++$j) { + $f = 0.0; + for ($i = $high; $i >= $m; --$i) { + $f += $this->ort[$i] * $this->H[$i][$j]; + } + $f /= $h; + for ($i = $m; $i <= $high; ++$i) { + $this->H[$i][$j] -= $f * $this->ort[$i]; + } + } + for ($i = 0; $i <= $high; ++$i) { + $f = 0.0; + for ($j = $high; $j >= $m; --$j) { + $f += $this->ort[$j] * $this->H[$i][$j]; + } + $f = $f / $h; + for ($j = $m; $j <= $high; ++$j) { + $this->H[$i][$j] -= $f * $this->ort[$j]; + } + } + $this->ort[$m] = $scale * $this->ort[$m]; + $this->H[$m][$m-1] = $scale * $g; + } + } + + // Accumulate transformations (Algol's ortran). + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + $this->V[$i][$j] = ($i == $j ? 1.0 : 0.0); + } + } + for ($m = $high-1; $m >= $low+1; --$m) { + if ($this->H[$m][$m-1] != 0.0) { + for ($i = $m+1; $i <= $high; ++$i) { + $this->ort[$i] = $this->H[$i][$m-1]; + } + for ($j = $m; $j <= $high; ++$j) { + $g = 0.0; + for ($i = $m; $i <= $high; ++$i) { + $g += $this->ort[$i] * $this->V[$i][$j]; + } + // Double division avoids possible underflow + $g = ($g / $this->ort[$m]) / $this->H[$m][$m-1]; + for ($i = $m; $i <= $high; ++$i) { + $this->V[$i][$j] += $g * $this->ort[$i]; + } + } + } + } + } + + + /** + * Performs complex division. + * + * @access private + */ + private function cdiv($xr, $xi, $yr, $yi) { + if (abs($yr) > abs($yi)) { + $r = $yi / $yr; + $d = $yr + $r * $yi; + $this->cdivr = ($xr + $r * $xi) / $d; + $this->cdivi = ($xi - $r * $xr) / $d; + } else { + $r = $yr / $yi; + $d = $yi + $r * $yr; + $this->cdivr = ($r * $xr + $xi) / $d; + $this->cdivi = ($r * $xi - $xr) / $d; + } + } + + + /** + * Nonsymmetric reduction from Hessenberg to real Schur form. + * + * Code is derived from the Algol procedure hqr2, + * by Martin and Wilkinson, Handbook for Auto. Comp., + * Vol.ii-Linear Algebra, and the corresponding + * Fortran subroutine in EISPACK. + * + * @access private + */ + private function hqr2 () { + // Initialize + $nn = $this->n; + $n = $nn - 1; + $low = 0; + $high = $nn - 1; + $eps = pow(2.0, -52.0); + $exshift = 0.0; + $p = $q = $r = $s = $z = 0; + // Store roots isolated by balanc and compute matrix norm + $norm = 0.0; + + for ($i = 0; $i < $nn; ++$i) { + if (($i < $low) OR ($i > $high)) { + $this->d[$i] = $this->H[$i][$i]; + $this->e[$i] = 0.0; + } + for ($j = max($i-1, 0); $j < $nn; ++$j) { + $norm = $norm + abs($this->H[$i][$j]); + } + } + + // Outer loop over eigenvalue index + $iter = 0; + while ($n >= $low) { + // Look for single small sub-diagonal element + $l = $n; + while ($l > $low) { + $s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]); + if ($s == 0.0) { + $s = $norm; + } + if (abs($this->H[$l][$l-1]) < $eps * $s) { + break; + } + --$l; + } + // Check for convergence + // One root found + if ($l == $n) { + $this->H[$n][$n] = $this->H[$n][$n] + $exshift; + $this->d[$n] = $this->H[$n][$n]; + $this->e[$n] = 0.0; + --$n; + $iter = 0; + // Two roots found + } else if ($l == $n-1) { + $w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; + $p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0; + $q = $p * $p + $w; + $z = sqrt(abs($q)); + $this->H[$n][$n] = $this->H[$n][$n] + $exshift; + $this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift; + $x = $this->H[$n][$n]; + // Real pair + if ($q >= 0) { + if ($p >= 0) { + $z = $p + $z; + } else { + $z = $p - $z; + } + $this->d[$n-1] = $x + $z; + $this->d[$n] = $this->d[$n-1]; + if ($z != 0.0) { + $this->d[$n] = $x - $w / $z; + } + $this->e[$n-1] = 0.0; + $this->e[$n] = 0.0; + $x = $this->H[$n][$n-1]; + $s = abs($x) + abs($z); + $p = $x / $s; + $q = $z / $s; + $r = sqrt($p * $p + $q * $q); + $p = $p / $r; + $q = $q / $r; + // Row modification + for ($j = $n-1; $j < $nn; ++$j) { + $z = $this->H[$n-1][$j]; + $this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j]; + $this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z; + } + // Column modification + for ($i = 0; $i <= n; ++$i) { + $z = $this->H[$i][$n-1]; + $this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n]; + $this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z; + } + // Accumulate transformations + for ($i = $low; $i <= $high; ++$i) { + $z = $this->V[$i][$n-1]; + $this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n]; + $this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z; + } + // Complex pair + } else { + $this->d[$n-1] = $x + $p; + $this->d[$n] = $x + $p; + $this->e[$n-1] = $z; + $this->e[$n] = -$z; + } + $n = $n - 2; + $iter = 0; + // No convergence yet + } else { + // Form shift + $x = $this->H[$n][$n]; + $y = 0.0; + $w = 0.0; + if ($l < $n) { + $y = $this->H[$n-1][$n-1]; + $w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; + } + // Wilkinson's original ad hoc shift + if ($iter == 10) { + $exshift += $x; + for ($i = $low; $i <= $n; ++$i) { + $this->H[$i][$i] -= $x; + } + $s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]); + $x = $y = 0.75 * $s; + $w = -0.4375 * $s * $s; + } + // MATLAB's new ad hoc shift + if ($iter == 30) { + $s = ($y - $x) / 2.0; + $s = $s * $s + $w; + if ($s > 0) { + $s = sqrt($s); + if ($y < $x) { + $s = -$s; + } + $s = $x - $w / (($y - $x) / 2.0 + $s); + for ($i = $low; $i <= $n; ++$i) { + $this->H[$i][$i] -= $s; + } + $exshift += $s; + $x = $y = $w = 0.964; + } + } + // Could check iteration count here. + $iter = $iter + 1; + // Look for two consecutive small sub-diagonal elements + $m = $n - 2; + while ($m >= $l) { + $z = $this->H[$m][$m]; + $r = $x - $z; + $s = $y - $z; + $p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1]; + $q = $this->H[$m+1][$m+1] - $z - $r - $s; + $r = $this->H[$m+2][$m+1]; + $s = abs($p) + abs($q) + abs($r); + $p = $p / $s; + $q = $q / $s; + $r = $r / $s; + if ($m == $l) { + break; + } + if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) < + $eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) { + break; + } + --$m; + } + for ($i = $m + 2; $i <= $n; ++$i) { + $this->H[$i][$i-2] = 0.0; + if ($i > $m+2) { + $this->H[$i][$i-3] = 0.0; + } + } + // Double QR step involving rows l:n and columns m:n + for ($k = $m; $k <= $n-1; ++$k) { + $notlast = ($k != $n-1); + if ($k != $m) { + $p = $this->H[$k][$k-1]; + $q = $this->H[$k+1][$k-1]; + $r = ($notlast ? $this->H[$k+2][$k-1] : 0.0); + $x = abs($p) + abs($q) + abs($r); + if ($x != 0.0) { + $p = $p / $x; + $q = $q / $x; + $r = $r / $x; + } + } + if ($x == 0.0) { + break; + } + $s = sqrt($p * $p + $q * $q + $r * $r); + if ($p < 0) { + $s = -$s; + } + if ($s != 0) { + if ($k != $m) { + $this->H[$k][$k-1] = -$s * $x; + } elseif ($l != $m) { + $this->H[$k][$k-1] = -$this->H[$k][$k-1]; + } + $p = $p + $s; + $x = $p / $s; + $y = $q / $s; + $z = $r / $s; + $q = $q / $p; + $r = $r / $p; + // Row modification + for ($j = $k; $j < $nn; ++$j) { + $p = $this->H[$k][$j] + $q * $this->H[$k+1][$j]; + if ($notlast) { + $p = $p + $r * $this->H[$k+2][$j]; + $this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z; + } + $this->H[$k][$j] = $this->H[$k][$j] - $p * $x; + $this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y; + } + // Column modification + for ($i = 0; $i <= min($n, $k+3); ++$i) { + $p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1]; + if ($notlast) { + $p = $p + $z * $this->H[$i][$k+2]; + $this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r; + } + $this->H[$i][$k] = $this->H[$i][$k] - $p; + $this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q; + } + // Accumulate transformations + for ($i = $low; $i <= $high; ++$i) { + $p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1]; + if ($notlast) { + $p = $p + $z * $this->V[$i][$k+2]; + $this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r; + } + $this->V[$i][$k] = $this->V[$i][$k] - $p; + $this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q; + } + } // ($s != 0) + } // k loop + } // check convergence + } // while ($n >= $low) + + // Backsubstitute to find vectors of upper triangular form + if ($norm == 0.0) { + return; + } + + for ($n = $nn-1; $n >= 0; --$n) { + $p = $this->d[$n]; + $q = $this->e[$n]; + // Real vector + if ($q == 0) { + $l = $n; + $this->H[$n][$n] = 1.0; + for ($i = $n-1; $i >= 0; --$i) { + $w = $this->H[$i][$i] - $p; + $r = 0.0; + for ($j = $l; $j <= $n; ++$j) { + $r = $r + $this->H[$i][$j] * $this->H[$j][$n]; + } + if ($this->e[$i] < 0.0) { + $z = $w; + $s = $r; + } else { + $l = $i; + if ($this->e[$i] == 0.0) { + if ($w != 0.0) { + $this->H[$i][$n] = -$r / $w; + } else { + $this->H[$i][$n] = -$r / ($eps * $norm); + } + // Solve real equations + } else { + $x = $this->H[$i][$i+1]; + $y = $this->H[$i+1][$i]; + $q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i]; + $t = ($x * $s - $z * $r) / $q; + $this->H[$i][$n] = $t; + if (abs($x) > abs($z)) { + $this->H[$i+1][$n] = (-$r - $w * $t) / $x; + } else { + $this->H[$i+1][$n] = (-$s - $y * $t) / $z; + } + } + // Overflow control + $t = abs($this->H[$i][$n]); + if (($eps * $t) * $t > 1) { + for ($j = $i; $j <= $n; ++$j) { + $this->H[$j][$n] = $this->H[$j][$n] / $t; + } + } + } + } + // Complex vector + } else if ($q < 0) { + $l = $n-1; + // Last vector component imaginary so matrix is triangular + if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) { + $this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1]; + $this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1]; + } else { + $this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q); + $this->H[$n-1][$n-1] = $this->cdivr; + $this->H[$n-1][$n] = $this->cdivi; + } + $this->H[$n][$n-1] = 0.0; + $this->H[$n][$n] = 1.0; + for ($i = $n-2; $i >= 0; --$i) { + // double ra,sa,vr,vi; + $ra = 0.0; + $sa = 0.0; + for ($j = $l; $j <= $n; ++$j) { + $ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1]; + $sa = $sa + $this->H[$i][$j] * $this->H[$j][$n]; + } + $w = $this->H[$i][$i] - $p; + if ($this->e[$i] < 0.0) { + $z = $w; + $r = $ra; + $s = $sa; + } else { + $l = $i; + if ($this->e[$i] == 0) { + $this->cdiv(-$ra, -$sa, $w, $q); + $this->H[$i][$n-1] = $this->cdivr; + $this->H[$i][$n] = $this->cdivi; + } else { + // Solve complex equations + $x = $this->H[$i][$i+1]; + $y = $this->H[$i+1][$i]; + $vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q; + $vi = ($this->d[$i] - $p) * 2.0 * $q; + if ($vr == 0.0 & $vi == 0.0) { + $vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z)); + } + $this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi); + $this->H[$i][$n-1] = $this->cdivr; + $this->H[$i][$n] = $this->cdivi; + if (abs($x) > (abs($z) + abs($q))) { + $this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x; + $this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x; + } else { + $this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q); + $this->H[$i+1][$n-1] = $this->cdivr; + $this->H[$i+1][$n] = $this->cdivi; + } + } + // Overflow control + $t = max(abs($this->H[$i][$n-1]),abs($this->H[$i][$n])); + if (($eps * $t) * $t > 1) { + for ($j = $i; $j <= $n; ++$j) { + $this->H[$j][$n-1] = $this->H[$j][$n-1] / $t; + $this->H[$j][$n] = $this->H[$j][$n] / $t; + } + } + } // end else + } // end for + } // end else for complex case + } // end for + + // Vectors of isolated roots + for ($i = 0; $i < $nn; ++$i) { + if ($i < $low | $i > $high) { + for ($j = $i; $j < $nn; ++$j) { + $this->V[$i][$j] = $this->H[$i][$j]; + } + } + } + + // Back transformation to get eigenvectors of original matrix + for ($j = $nn-1; $j >= $low; --$j) { + for ($i = $low; $i <= $high; ++$i) { + $z = 0.0; + for ($k = $low; $k <= min($j,$high); ++$k) { + $z = $z + $this->V[$i][$k] * $this->H[$k][$j]; + } + $this->V[$i][$j] = $z; + } + } + } // end hqr2 + + + /** + * Constructor: Check for symmetry, then construct the eigenvalue decomposition + * + * @access public + * @param A Square matrix + * @return Structure to access D and V. + */ + public function __construct($Arg) { + $this->A = $Arg->getArray(); + $this->n = $Arg->getColumnDimension(); + + $issymmetric = true; + for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) { + for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) { + $issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]); + } + } + + if ($issymmetric) { + $this->V = $this->A; + // Tridiagonalize. + $this->tred2(); + // Diagonalize. + $this->tql2(); + } else { + $this->H = $this->A; + $this->ort = array(); + // Reduce to Hessenberg form. + $this->orthes(); + // Reduce Hessenberg to real Schur form. + $this->hqr2(); + } + } + + + /** + * Return the eigenvector matrix + * + * @access public + * @return V + */ + public function getV() { + return new Matrix($this->V, $this->n, $this->n); + } + + + /** + * Return the real parts of the eigenvalues + * + * @access public + * @return real(diag(D)) + */ + public function getRealEigenvalues() { + return $this->d; + } + + + /** + * Return the imaginary parts of the eigenvalues + * + * @access public + * @return imag(diag(D)) + */ + public function getImagEigenvalues() { + return $this->e; + } + + + /** + * Return the block diagonal eigenvalue matrix + * + * @access public + * @return D + */ + public function getD() { + for ($i = 0; $i < $this->n; ++$i) { + $D[$i] = array_fill(0, $this->n, 0.0); + $D[$i][$i] = $this->d[$i]; + if ($this->e[$i] == 0) { + continue; + } + $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1; + $D[$i][$o] = $this->e[$i]; + } + return new Matrix($D); + } + +} // class EigenvalueDecomposition diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/LUDecomposition.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/LUDecomposition.php index de177a5f6..4fd43f91f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/LUDecomposition.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/LUDecomposition.php @@ -1,222 +1,255 @@ = n, the LU decomposition is an m-by-n -* unit lower triangular matrix L, an n-by-n upper triangular matrix U, -* and a permutation vector piv of length m so that A(piv,:) = L*U. -* If m < n, then L is m-by-m and U is m-by-n. -* -* The LU decompostion with pivoting always exists, even if the matrix is -* singular, so the constructor will never fail. The primary use of the -* LU decomposition is in the solution of square systems of simultaneous -* linear equations. This will fail if isNonsingular() returns false. -* -* @author Paul Meagher -* @author Bartosz Matosiuk -* @author Michael Bommarito -* @version 1.1 -* @license PHP v3.0 -*/ + * @package JAMA + * + * For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n + * unit lower triangular matrix L, an n-by-n upper triangular matrix U, + * and a permutation vector piv of length m so that A(piv,:) = L*U. + * If m < n, then L is m-by-m and U is m-by-n. + * + * The LU decompostion with pivoting always exists, even if the matrix is + * singular, so the constructor will never fail. The primary use of the + * LU decomposition is in the solution of square systems of simultaneous + * linear equations. This will fail if isNonsingular() returns false. + * + * @author Paul Meagher + * @author Bartosz Matosiuk + * @author Michael Bommarito + * @version 1.1 + * @license PHP v3.0 + */ class LUDecomposition { - /** - * Decomposition storage - * @var array - */ - var $LU = array(); - - /** - * Row dimension. - * @var int - */ - var $m; - /** - * Column dimension. - * @var int - */ - var $n; - - /** - * Pivot sign. - * @var int - */ - var $pivsign; + /** + * Decomposition storage + * @var array + */ + private $LU = array(); - /** - * Internal storage of pivot vector. - * @var array - */ - var $piv = array(); - - /** - * LU Decomposition constructor. - * @param $A Rectangular matrix - * @return Structure to access L, U and piv. - */ - function LUDecomposition ($A) { - if( is_a($A, 'Matrix') ) { - // Use a "left-looking", dot-product, Crout/Doolittle algorithm. - $this->LU = $A->getArrayCopy(); - $this->m = $A->getRowDimension(); - $this->n = $A->getColumnDimension(); - for ($i = 0; $i < $this->m; $i++) - $this->piv[$i] = $i; - $this->pivsign = 1; - $LUrowi = array(); - $LUcolj = array(); - // Outer loop. - for ($j = 0; $j < $this->n; $j++) { - // Make a copy of the j-th column to localize references. - for ($i = 0; $i < $this->m; $i++) - $LUcolj[$i] = &$this->LU[$i][$j]; - // Apply previous transformations. - for ($i = 0; $i < $this->m; $i++) { - $LUrowi = $this->LU[$i]; - // Most of the time is spent in the following dot product. - $kmax = min($i,$j); - $s = 0.0; - for ($k = 0; $k < $kmax; $k++) - $s += $LUrowi[$k]*$LUcolj[$k]; - $LUrowi[$j] = $LUcolj[$i] -= $s; - } - // Find pivot and exchange if necessary. - $p = $j; - for ($i = $j+1; $i < $this->m; $i++) { - if (abs($LUcolj[$i]) > abs($LUcolj[$p])) - $p = $i; - } - if ($p != $j) { - for ($k = 0; $k < $this->n; $k++) { - $t = $this->LU[$p][$k]; - $this->LU[$p][$k] = $this->LU[$j][$k]; - $this->LU[$j][$k] = $t; - } - $k = $this->piv[$p]; - $this->piv[$p] = $this->piv[$j]; - $this->piv[$j] = $k; - $this->pivsign = $this->pivsign * -1; - } - // Compute multipliers. - if ( ($j < $this->m) AND ($this->LU[$j][$j] != 0.0) ) { - for ($i = $j+1; $i < $this->m; $i++) - $this->LU[$i][$j] /= $this->LU[$j][$j]; - } - } - } else { - trigger_error(ArgumentTypeException, ERROR); - } - } - - /** - * Get lower triangular factor. - * @return array Lower triangular factor - */ - function getL () { - for ($i = 0; $i < $this->m; $i++) { - for ($j = 0; $j < $this->n; $j++) { - if ($i > $j) - $L[$i][$j] = $this->LU[$i][$j]; - else if($i == $j) - $L[$i][$j] = 1.0; - else - $L[$i][$j] = 0.0; - } - } - return new Matrix($L); - } + /** + * Row dimension. + * @var int + */ + private $m; - /** - * Get upper triangular factor. - * @return array Upper triangular factor - */ - function getU () { - for ($i = 0; $i < $this->n; $i++) { - for ($j = 0; $j < $this->n; $j++) { - if ($i <= $j) - $U[$i][$j] = $this->LU[$i][$j]; - else - $U[$i][$j] = 0.0; - } - } - return new Matrix($U); - } - - /** - * Return pivot permutation vector. - * @return array Pivot vector - */ - function getPivot () { - return $this->piv; - } - - /** - * Alias for getPivot - * @see getPivot - */ - function getDoublePivot () { - return $this->getPivot(); - } + /** + * Column dimension. + * @var int + */ + private $n; - /** - * Is the matrix nonsingular? - * @return true if U, and hence A, is nonsingular. - */ - function isNonsingular () { - for ($j = 0; $j < $this->n; $j++) { - if ($this->LU[$j][$j] == 0) - return false; - } - return true; - } + /** + * Pivot sign. + * @var int + */ + private $pivsign; - /** - * Count determinants - * @return array d matrix deterninat - */ - function det() { - if ($this->m == $this->n) { - $d = $this->pivsign; - for ($j = 0; $j < $this->n; $j++) - $d *= $this->LU[$j][$j]; - return $d; - } else { - trigger_error(MatrixDimensionException, ERROR); - } - } - - /** - * Solve A*X = B - * @param $B A Matrix with as many rows as A and any number of columns. - * @return X so that L*U*X = B(piv,:) - * @exception IllegalArgumentException Matrix row dimensions must agree. - * @exception RuntimeException Matrix is singular. - */ - function solve($B) { - if ($B->getRowDimension() == $this->m) { - if ($this->isNonsingular()) { - // Copy right hand side with pivoting - $nx = $B->getColumnDimension(); - $X = $B->getMatrix($this->piv, 0, $nx-1); - // Solve L*Y = B(piv,:) - for ($k = 0; $k < $this->n; $k++) - for ($i = $k+1; $i < $this->n; $i++) - for ($j = 0; $j < $nx; $j++) - $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; - // Solve U*X = Y; - for ($k = $this->n-1; $k >= 0; $k--) { - for ($j = 0; $j < $nx; $j++) - $X->A[$k][$j] /= $this->LU[$k][$k]; - for ($i = 0; $i < $k; $i++) - for ($j = 0; $j < $nx; $j++) - $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; - } - return $X; - } else { - trigger_error(MatrixSingularException, ERROR); - } - } else { - trigger_error(MatrixSquareException, ERROR); - } - } -} + /** + * Internal storage of pivot vector. + * @var array + */ + private $piv = array(); + + + /** + * LU Decomposition constructor. + * + * @param $A Rectangular matrix + * @return Structure to access L, U and piv. + */ + public function __construct($A) { + if ($A instanceof Matrix) { + // Use a "left-looking", dot-product, Crout/Doolittle algorithm. + $this->LU = $A->getArrayCopy(); + $this->m = $A->getRowDimension(); + $this->n = $A->getColumnDimension(); + for ($i = 0; $i < $this->m; ++$i) { + $this->piv[$i] = $i; + } + $this->pivsign = 1; + $LUrowi = $LUcolj = array(); + + // Outer loop. + for ($j = 0; $j < $this->n; ++$j) { + // Make a copy of the j-th column to localize references. + for ($i = 0; $i < $this->m; ++$i) { + $LUcolj[$i] = &$this->LU[$i][$j]; + } + // Apply previous transformations. + for ($i = 0; $i < $this->m; ++$i) { + $LUrowi = $this->LU[$i]; + // Most of the time is spent in the following dot product. + $kmax = min($i,$j); + $s = 0.0; + for ($k = 0; $k < $kmax; ++$k) { + $s += $LUrowi[$k] * $LUcolj[$k]; + } + $LUrowi[$j] = $LUcolj[$i] -= $s; + } + // Find pivot and exchange if necessary. + $p = $j; + for ($i = $j+1; $i < $this->m; ++$i) { + if (abs($LUcolj[$i]) > abs($LUcolj[$p])) { + $p = $i; + } + } + if ($p != $j) { + for ($k = 0; $k < $this->n; ++$k) { + $t = $this->LU[$p][$k]; + $this->LU[$p][$k] = $this->LU[$j][$k]; + $this->LU[$j][$k] = $t; + } + $k = $this->piv[$p]; + $this->piv[$p] = $this->piv[$j]; + $this->piv[$j] = $k; + $this->pivsign = $this->pivsign * -1; + } + // Compute multipliers. + if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) { + for ($i = $j+1; $i < $this->m; ++$i) { + $this->LU[$i][$j] /= $this->LU[$j][$j]; + } + } + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function __construct() + + + /** + * Get lower triangular factor. + * + * @return array Lower triangular factor + */ + public function getL() { + for ($i = 0; $i < $this->m; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i > $j) { + $L[$i][$j] = $this->LU[$i][$j]; + } elseif ($i == $j) { + $L[$i][$j] = 1.0; + } else { + $L[$i][$j] = 0.0; + } + } + } + return new Matrix($L); + } // function getL() + + + /** + * Get upper triangular factor. + * + * @return array Upper triangular factor + */ + public function getU() { + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i <= $j) { + $U[$i][$j] = $this->LU[$i][$j]; + } else { + $U[$i][$j] = 0.0; + } + } + } + return new Matrix($U); + } // function getU() + + + /** + * Return pivot permutation vector. + * + * @return array Pivot vector + */ + public function getPivot() { + return $this->piv; + } // function getPivot() + + + /** + * Alias for getPivot + * + * @see getPivot + */ + public function getDoublePivot() { + return $this->getPivot(); + } // function getDoublePivot() + + + /** + * Is the matrix nonsingular? + * + * @return true if U, and hence A, is nonsingular. + */ + public function isNonsingular() { + for ($j = 0; $j < $this->n; ++$j) { + if ($this->LU[$j][$j] == 0) { + return false; + } + } + return true; + } // function isNonsingular() + + + /** + * Count determinants + * + * @return array d matrix deterninat + */ + public function det() { + if ($this->m == $this->n) { + $d = $this->pivsign; + for ($j = 0; $j < $this->n; ++$j) { + $d *= $this->LU[$j][$j]; + } + return $d; + } else { + throw new Exception(JAMAError(MatrixDimensionException)); + } + } // function det() + + + /** + * Solve A*X = B + * + * @param $B A Matrix with as many rows as A and any number of columns. + * @return X so that L*U*X = B(piv,:) + * @exception IllegalArgumentException Matrix row dimensions must agree. + * @exception RuntimeException Matrix is singular. + */ + public function solve($B) { + if ($B->getRowDimension() == $this->m) { + if ($this->isNonsingular()) { + // Copy right hand side with pivoting + $nx = $B->getColumnDimension(); + $X = $B->getMatrix($this->piv, 0, $nx-1); + // Solve L*Y = B(piv,:) + for ($k = 0; $k < $this->n; ++$k) { + for ($i = $k+1; $i < $this->n; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; + } + } + } + // Solve U*X = Y; + for ($k = $this->n-1; $k >= 0; --$k) { + for ($j = 0; $j < $nx; ++$j) { + $X->A[$k][$j] /= $this->LU[$k][$k]; + } + for ($i = 0; $i < $k; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; + } + } + } + return $X; + } else { + throw new Exception(JAMAError(MatrixSingularException)); + } + } else { + throw new Exception(JAMAError(MatrixSquareException)); + } + } // function solve() + +} // class LUDecomposition diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php index c1b79ae04..efababbc4 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php @@ -1,1331 +1,1361 @@ 0 ) { - - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - - //Square matrix - n x n - case 'integer': - $this->m = $args[0]; - $this->n = $args[0]; - $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); - break; - - //Rectangular matrix - m x n - case 'integer,integer': - $this->m = $args[0]; - $this->n = $args[1]; - $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); - break; - - //Rectangular matrix constant-filled - m x n filled with c - case 'integer,integer,integer': - $this->m = $args[0]; - $this->n = $args[1]; - $this->A = array_fill(0, $this->m, array_fill(0, $this->n, $args[2])); - break; - - //Rectangular matrix constant-filled - m x n filled with c - case 'integer,integer,double': - $this->m = $args[0]; - $this->n = $args[1]; - $this->A = array_fill(0, $this->m, array_fill(0, $this->n, $args[2])); - break; - - //Rectangular matrix - m x n initialized from 2D array - case 'array': - $this->m = count($args[0]); - $this->n = count($args[0][0]); - $this->A = $args[0]; - break; - - //Rectangular matrix - m x n initialized from 2D array - case 'array,integer,integer': - $this->m = $args[1]; - $this->n = $args[2]; - $this->A = $args[0]; - break; - - //Rectangular matrix - m x n initialized from packed array - case 'array,integer': - $this->m = $args[1]; - - if ($this->m != 0) - $this->n = count($args[0]) / $this->m; - else - $this->n = 0; - - if ($this->m * $this->n == count($args[0])) - for($i = 0; $i < $this->m; $i++) - for($j = 0; $j < $this->n; $j++) - $this->A[$i][$j] = $args[0][$i + $j * $this->m]; - else - trigger_error(ArrayLengthException, ERROR); - - break; - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else - trigger_error(PolymorphicArgumentException, ERROR); - } - - /** - * getArray - * @return array Matrix array - */ - function &getArray() { - return $this->A; - } - - /** - * getArrayCopy - * @return array Matrix array copy - */ - function getArrayCopy() { - return $this->A; - } - - /** Construct a matrix from a copy of a 2-D array. - * @param double A[][] Two-dimensional array of doubles. - * @exception IllegalArgumentException All rows must have the same length - */ - function constructWithCopy($A) { - $this->m = count($A); - $this->n = count($A[0]); - $X = new Matrix($this->m, $this->n); - for ($i = 0; $i < $this->m; $i++) { - if (count($A[$i]) != $this->n) - trigger_error(RowLengthException, ERROR); - for ($j = 0; $j < $this->n; $j++) - $X->A[$i][$j] = $A[$i][$j]; - } - return $X; - } - - /** - * getColumnPacked - * Get a column-packed array - * @return array Column-packed matrix array - */ - function getColumnPackedCopy() { - $P = array(); - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - array_push($P, $this->A[$j][$i]); - } - } - return $P; - } - - /** - * getRowPacked - * Get a row-packed array - * @return array Row-packed matrix array - */ - function getRowPackedCopy() { - $P = array(); - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - array_push($P, $this->A[$i][$j]); - } - } - return $P; - } - - /** - * getRowDimension - * @return int Row dimension - */ - function getRowDimension() { - return $this->m; - } - - /** - * getColumnDimension - * @return int Column dimension - */ - function getColumnDimension() { - return $this->n; - } - - /** - * get - * Get the i,j-th element of the matrix. - * @param int $i Row position - * @param int $j Column position - * @return mixed Element (int/float/double) - */ - function get( $i = null, $j = null ) { - return $this->A[$i][$j]; - } - - /** - * getMatrix - * Get a submatrix - * @param int $i0 Initial row index - * @param int $iF Final row index - * @param int $j0 Initial column index - * @param int $jF Final column index - * @return Matrix Submatrix - */ - function getMatrix() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - switch( $match ) { - - //A($i0...; $j0...) - case 'integer,integer': - list($i0, $j0) = $args; - $m = $i0 >= 0 ? $this->m - $i0 : trigger_error(ArgumentBoundsException, ERROR); - $n = $j0 >= 0 ? $this->n - $j0 : trigger_error(ArgumentBoundsException, ERROR); - $R = new Matrix($m, $n); - - for($i = $i0; $i < $this->m; $i++) - for($j = $j0; $j < $this->n; $j++) - $R->set($i, $j, $this->A[$i][$j]); - - return $R; - break; - - //A($i0...$iF; $j0...$jF) - case 'integer,integer,integer,integer': - list($i0, $iF, $j0, $jF) = $args; - $m = ( ($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0) ) ? $iF - $i0 : trigger_error(ArgumentBoundsException, ERROR); - $n = ( ($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0) ) ? $jF - $j0 : trigger_error(ArgumentBoundsException, ERROR); - $R = new Matrix($m+1, $n+1); - - for($i = $i0; $i <= $iF; $i++) - for($j = $j0; $j <= $jF; $j++) - $R->set($i - $i0, $j - $j0, $this->A[$i][$j]); - - return $R; - break; - - //$R = array of row indices; $C = array of column indices - case 'array,array': - list($RL, $CL) = $args; - $m = count($RL) > 0 ? count($RL) : trigger_error(ArgumentBoundsException, ERROR); - $n = count($CL) > 0 ? count($CL) : trigger_error(ArgumentBoundsException, ERROR); - $R = new Matrix($m, $n); - - for($i = 0; $i < $m; $i++) - for($j = 0; $j < $n; $j++) - $R->set($i - $i0, $j - $j0, $this->A[$RL[$i]][$CL[$j]]); - - return $R; - break; - - //$RL = array of row indices; $CL = array of column indices - case 'array,array': - list($RL, $CL) = $args; - $m = count($RL) > 0 ? count($RL) : trigger_error(ArgumentBoundsException, ERROR); - $n = count($CL) > 0 ? count($CL) : trigger_error(ArgumentBoundsException, ERROR); - $R = new Matrix($m, $n); - - for($i = 0; $i < $m; $i++) - for($j = 0; $j < $n; $j++) - $R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]); - - return $R; - break; - - //A($i0...$iF); $CL = array of column indices - case 'integer,integer,array': - list($i0, $iF, $CL) = $args; - $m = ( ($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0) ) ? $iF - $i0 : trigger_error(ArgumentBoundsException, ERROR); - $n = count($CL) > 0 ? count($CL) : trigger_error(ArgumentBoundsException, ERROR); - $R = new Matrix($m, $n); - - for($i = $i0; $i < $iF; $i++) - for($j = 0; $j < $n; $j++) - $R->set($i - $i0, $j, $this->A[$RL[$i]][$j]); - - return $R; - break; - - //$RL = array of row indices - case 'array,integer,integer': - list($RL, $j0, $jF) = $args; - $m = count($RL) > 0 ? count($RL) : trigger_error(ArgumentBoundsException, ERROR); - $n = ( ($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0) ) ? $jF - $j0 : trigger_error(ArgumentBoundsException, ERROR); - $R = new Matrix($m, $n+1); - - for($i = 0; $i < $m; $i++) - for($j = $j0; $j <= $jF; $j++) - $R->set($i, $j - $j0, $this->A[$RL[$i]][$j]); - - return $R; - break; - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * setMatrix - * Set a submatrix - * @param int $i0 Initial row index - * @param int $j0 Initial column index - * @param mixed $S Matrix/Array submatrix - * ($i0, $j0, $S) $S = Matrix - * ($i0, $j0, $S) $S = Array - */ - function setMatrix( ) { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'integer,integer,object': - $M = is_a($args[2], 'Matrix') ? $args[2] : trigger_error(ArgumentTypeException, ERROR); - $i0 = ( ($args[0] + $M->m) <= $this->m ) ? $args[0] : trigger_error(ArgumentBoundsException, ERROR); - $j0 = ( ($args[1] + $M->n) <= $this->n ) ? $args[1] : trigger_error(ArgumentBoundsException, ERROR); - - for($i = $i0; $i < $i0 + $M->m; $i++) { - for($j = $j0; $j < $j0 + $M->n; $j++) { - $this->A[$i][$j] = $M->get($i - $i0, $j - $j0); - } - } - - break; - - case 'integer,integer,array': - $M = new Matrix($args[2]); - $i0 = ( ($args[0] + $M->m) <= $this->m ) ? $args[0] : trigger_error(ArgumentBoundsException, ERROR); - $j0 = ( ($args[1] + $M->n) <= $this->n ) ? $args[1] : trigger_error(ArgumentBoundsException, ERROR); - - for($i = $i0; $i < $i0 + $M->m; $i++) { - for($j = $j0; $j < $j0 + $M->n; $j++) { - $this->A[$i][$j] = $M->get($i - $i0, $j - $j0); - } - } - - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * checkMatrixDimensions - * Is matrix B the same size? - * @param Matrix $B Matrix B - * @return boolean - */ - function checkMatrixDimensions( $B = null ) { - if( is_a($B, 'Matrix') ) - if( ($this->m == $B->m) && ($this->n == $B->n) ) - return true; - else - trigger_error(MatrixDimensionException, ERROR); - - else - trigger_error(ArgumentTypeException, ERROR); - } - - - - /** - * set - * Set the i,j-th element of the matrix. - * @param int $i Row position - * @param int $j Column position - * @param mixed $c Int/float/double value - * @return mixed Element (int/float/double) - */ - function set( $i = null, $j = null, $c = null ) { - // Optimized set version just has this - $this->A[$i][$j] = $c; - /* - if( is_int($i) && is_int($j) && is_numeric($c) ) { - if( ( $i < $this->m ) && ( $j < $this->n ) ) { - $this->A[$i][$j] = $c; - } else { - echo "A[$i][$j] = $c
"; - trigger_error(ArgumentBoundsException, WARNING); - } - } else { - trigger_error(ArgumentTypeException, WARNING); - } - */ - } - - /** - * identity - * Generate an identity matrix. - * @param int $m Row dimension - * @param int $n Column dimension - * @return Matrix Identity matrix - */ - function &identity( $m = null, $n = null ) { - return Matrix::diagonal($m, $n, 1); - } - - /** - * diagonal - * Generate a diagonal matrix - * @param int $m Row dimension - * @param int $n Column dimension - * @param mixed $c Diagonal value - * @return Matrix Diagonal matrix - */ - function &diagonal( $m = null, $n = null, $c = 1 ) { - $R = new Matrix($m, $n); - for($i = 0; $i < $m; $i++) - $R->set($i, $i, $c); - return $R; - } - - /** - * filled - * Generate a filled matrix - * @param int $m Row dimension - * @param int $n Column dimension - * @param int $c Fill constant - * @return Matrix Filled matrix - */ - function &filled( $m = null, $n = null, $c = 0 ) { - if( is_int($m) && is_int($n) && is_numeric($c) ) { - $R = new Matrix($m, $n, $c); - return $R; - } else { - trigger_error(ArgumentTypeException, ERROR); - } - } - - /** - * random - * Generate a random matrix - * @param int $m Row dimension - * @param int $n Column dimension - * @return Matrix Random matrix - */ - function &random( $m = null, $n = null, $a = RAND_MIN, $b = RAND_MAX ) { - if( is_int($m) && is_int($n) && is_numeric($a) && is_numeric($b) ) { - $R = new Matrix($m, $n); - - for($i = 0; $i < $m; $i++) - for($j = 0; $j < $n; $j++) - $R->set($i, $j, mt_rand($a, $b)); - - return $R; - } else { - trigger_error(ArgumentTypeException, ERROR); - } - } - - /** - * packed - * Alias for getRowPacked - * @return array Packed array - */ - function &packed() { - return $this->getRowPacked(); - } - - - /** - * getMatrixByRow - * Get a submatrix by row index/range - * @param int $i0 Initial row index - * @param int $iF Final row index - * @return Matrix Submatrix - */ - function getMatrixByRow( $i0 = null, $iF = null ) { - if( is_int($i0) ) { - if( is_int($iF) ) - return $this->getMatrix($i0, 0, $iF + 1, $this->n); - else - return $this->getMatrix($i0, 0, $i0 + 1, $this->n); - } else - trigger_error(ArgumentTypeException, ERROR); - } - - /** - * getMatrixByCol - * Get a submatrix by column index/range - * @param int $i0 Initial column index - * @param int $iF Final column index - * @return Matrix Submatrix - */ - function getMatrixByCol( $j0 = null, $jF = null ) { - if( is_int($j0) ) { - if( is_int($jF) ) - return $this->getMatrix(0, $j0, $this->m, $jF + 1); - else - return $this->getMatrix(0, $j0, $this->m, $j0 + 1); - } else - trigger_error(ArgumentTypeException, ERROR); - } - - /** - * transpose - * Tranpose matrix - * @return Matrix Transposed matrix - */ - function transpose() { - $R = new Matrix($this->n, $this->m); - - for($i = 0; $i < $this->m; $i++) - for($j = 0; $j < $this->n; $j++) - $R->set($j, $i, $this->A[$i][$j]); - - return $R; - } - -/* - public Matrix transpose () { - Matrix X = new Matrix(n,m); - double[][] C = X.getArray(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - C[j][i] = A[i][j]; - } - } - return X; - } -*/ - - /** - * norm1 - * One norm - * @return float Maximum column sum - */ - function norm1() { - $r = 0; - - for($j = 0; $j < $this->n; $j++) { - $s = 0; - - for($i = 0; $i < $this->m; $i++) { - $s += abs($this->A[$i][$j]); - } - - $r = ( $r > $s ) ? $r : $s; - } - - return $r; - } - - - /** - * norm2 - * Maximum singular value - * @return float Maximum singular value - */ - function norm2() { - - } - - /** - * normInf - * Infinite norm - * @return float Maximum row sum - */ - function normInf() { - $r = 0; - - for($i = 0; $i < $this->m; $i++) { - $s = 0; - - for($j = 0; $j < $this->n; $j++) { - $s += abs($this->A[$i][$j]); - } - - $r = ( $r > $s ) ? $r : $s; - } - - return $r; - } - - /** - * normF - * Frobenius norm - * @return float Square root of the sum of all elements squared - */ - function normF() { - $f = 0; - for ($i = 0; $i < $this->m; $i++) - for ($j = 0; $j < $this->n; $j++) - $f = hypo($f,$this->A[$i][$j]); - return $f; - } - - /** - * Matrix rank - * @return effective numerical rank, obtained from SVD. - */ - function rank () { - $svd = new SingularValueDecomposition($this); - return $svd->rank(); - } - - /** - * Matrix condition (2 norm) - * @return ratio of largest to smallest singular value. - */ - function cond () { - $svd = new SingularValueDecomposition($this); - return $svd->cond(); - } - - /** - * trace - * Sum of diagonal elements - * @return float Sum of diagonal elements - */ - function trace() { - $s = 0; - $n = min($this->m, $this->n); - - for($i = 0; $i < $n; $i++) - $s += $this->A[$i][$i]; - - return $s; - } - - - /** - * uminus - * Unary minus matrix -A - * @return Matrix Unary minus matrix - */ - function uminus() { - - } - - /** - * plus - * A + B - * @param mixed $B Matrix/Array - * @return Matrix Sum - */ - function plus() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - //$this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]); - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - //$this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]); - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * plusEquals - * A = A + B - * @param mixed $B Matrix/Array - * @return Matrix Sum - */ - function &plusEquals() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] += $M->get($i, $j); - } - } - - return $this; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] += $M->get($i, $j); - } - } - - return $this; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * minus - * A - B - * @param mixed $B Matrix/Array - * @return Matrix Sum - */ - function minus() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]); - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]); - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * minusEquals - * A = A - B - * @param mixed $B Matrix/Array - * @return Matrix Sum - */ - function &minusEquals() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] -= $M->get($i, $j); - } - } - - return $this; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] -= $M->get($i, $j); - } - } - - return $this; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * arrayTimes - * Element-by-element multiplication - * Cij = Aij * Bij - * @param mixed $B Matrix/Array - * @return Matrix Matrix Cij - */ - function arrayTimes() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]); - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]); - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - - /** - * arrayTimesEquals - * Element-by-element multiplication - * Aij = Aij * Bij - * @param mixed $B Matrix/Array - * @return Matrix Matrix Aij - */ - function &arrayTimesEquals() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] *= $M->get($i, $j); - } - } - - return $this; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] *= $M->get($i, $j); - } - } - - return $this; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * arrayRightDivide - * Element-by-element right division - * A / B - * @param Matrix $B Matrix B - * @return Matrix Division result - */ - function arrayRightDivide() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $this->A[$i][$j] / $M->get($i, $j) ); - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $this->A[$i][$j] / $M->get($i, $j)); - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * arrayRightDivideEquals - * Element-by-element right division - * Aij = Aij / Bij - * @param mixed $B Matrix/Array - * @return Matrix Matrix Aij - */ - function &arrayRightDivideEquals() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j); - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j); - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * arrayLeftDivide - * Element-by-element Left division - * A / B - * @param Matrix $B Matrix B - * @return Matrix Division result - */ - function arrayLeftDivide() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j] ); - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j] ); - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * arrayLeftDivideEquals - * Element-by-element Left division - * Aij = Aij / Bij - * @param mixed $B Matrix/Array - * @return Matrix Matrix Aij - */ - function &arrayLeftDivideEquals() { - if( func_num_args() > 0 ) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - - switch( $match ) { - case 'object': - $M = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j]; - } - } - - return $M; - break; - - case 'array': - $M = new Matrix($args[0]); - $this->checkMatrixDimensions($M); - - for($i = 0; $i < $this->m; $i++) { - for($j = 0; $j < $this->n; $j++) { - $this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j]; - } - } - - return $M; - break; - - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else { - trigger_error(PolymorphicArgumentException, ERROR); - } - } - - /** - * times - * Matrix multiplication - * @param mixed $n Matrix/Array/Scalar - * @return Matrix Product - */ - function times() { - if(func_num_args() > 0) { - $args = func_get_args(); - $match = implode(",", array_map('gettype', $args)); - switch($match) { - case 'object': - $B = is_a($args[0], 'Matrix') ? $args[0] : trigger_error(ArgumentTypeException, ERROR); - if($this->n == $B->m) { - $C = new Matrix($this->m, $B->n); - for($j = 0; $j < $B->n; $j++ ) { - for ($k = 0; $k < $this->n; $k++) - $Bcolj[$k] = $B->A[$k][$j]; - for($i = 0; $i < $this->m; $i++ ) { - $Arowi = $this->A[$i]; - $s = 0; - for( $k = 0; $k < $this->n; $k++ ) - $s += $Arowi[$k] * $Bcolj[$k]; - $C->A[$i][$j] = $s; - } - } - return $C; - } else - trigger_error(MatrixDimensionMismatch, FATAL); - break; - - case 'array': - $B = new Matrix($args[0]); - if($this->n == $B->m) { - $C = new Matrix($this->m, $B->n); - for($i = 0; $i < $C->m; $i++) { - for($j = 0; $j < $C->n; $j++) { - $s = "0"; - for($k = 0; $k < $C->n; $k++) - $s += $this->A[$i][$k] * $B->A[$k][$j]; - $C->A[$i][$j] = $s; - } - } - return $C; - } else - trigger_error(MatrixDimensionMismatch, FATAL); - return $M; - break; - case 'integer': - $C = new Matrix($this->A); - for($i = 0; $i < $C->m; $i++) - for($j = 0; $j < $C->n; $j++) - $C->A[$i][$j] *= $args[0]; - return $C; - break; - case 'double': - $C = new Matrix($this->m, $this->n); - for($i = 0; $i < $C->m; $i++) - for($j = 0; $j < $C->n; $j++) - $C->A[$i][$j] = $args[0] * $this->A[$i][$j]; - return $C; - break; - case 'float': - $C = new Matrix($this->A); - for($i = 0; $i < $C->m; $i++) - for($j = 0; $j < $C->n; $j++) - $C->A[$i][$j] *= $args[0]; - return $C; - break; - default: - trigger_error(PolymorphicArgumentException, ERROR); - break; - } - } else - trigger_error(PolymorphicArgumentException, ERROR); - } - - /** - * chol - * Cholesky decomposition - * @return Matrix Cholesky decomposition - */ - function chol() { - return new CholeskyDecomposition($this); - } - - /** - * lu - * LU decomposition - * @return Matrix LU decomposition - */ - function lu() { - return new LUDecomposition($this); - } - - /** - * qr - * QR decomposition - * @return Matrix QR decomposition - */ - function qr() { - return new QRDecomposition($this); - } - - - /** - * eig - * Eigenvalue decomposition - * @return Matrix Eigenvalue decomposition - */ - function eig() { - return new EigenvalueDecomposition($this); - } - - /** - * svd - * Singular value decomposition - * @return Singular value decomposition - */ - function svd() { - return new SingularValueDecomposition($this); - } - - /** - * Solve A*X = B. - * @param Matrix $B Right hand side - * @return Matrix ... Solution if A is square, least squares solution otherwise - */ - function solve($B) { - if ($this->m == $this->n) { - $LU = new LUDecomposition($this); - return $LU->solve($B); - } else { - $QR = new QRDecomposition($this); - return $QR->solve($B); - } - } - - /** - * Matrix inverse or pseudoinverse. - * @return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise. - */ - function inverse() { - return $this->solve($this->identity($this->m, $this->m)); - } - - - /** - * det - * Calculate determinant - * @return float Determinant - */ - function det() { - $L = new LUDecomposition($this); - return $L->det(); - } - - /** - * Older debugging utility for backwards compatability. - * @return html version of matrix - */ - function mprint($A, $format="%01.2f", $width=2) { - $spacing = ""; - $m = count($A); - $n = count($A[0]); - for($i = 0; $i < $width; $i++) - $spacing .= " "; - for ($i = 0; $i < $m; $i++) { - for ($j = 0; $j < $n; $j++) { - $formatted = sprintf($format, $A[$i][$j]); - echo $formatted . $spacing; - } - echo "
"; - } - } - - /** - * Debugging utility. - * @return Output HTML representation of matrix - */ - function toHTML($width=2) { - print( ''); - for( $i = 0; $i < $this->m; $i++ ) { - print( '' ); - for( $j = 0; $j < $this->n; $j++ ) - print( '' ); - print( ''); - } - print( '
' . $this->A[$i][$j] . '
' ); - } +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); } + +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/utils/Error.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/utils/Maths.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/CholeskyDecomposition.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/LUDecomposition.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/QRDecomposition.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/EigenvalueDecomposition.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/SingularValueDecomposition.php'; + +/* + * Matrix class + * + * @author Paul Meagher + * @author Michael Bommarito + * @author Lukasz Karapuda + * @author Bartek Matosiuk + * @version 1.8 + * @license PHP v3.0 + * @see http://math.nist.gov/javanumerics/jama/ + */ +class Matrix { + + /** + * Matrix storage + * + * @var array + * @access public + */ + public $A = array(); + + /** + * Matrix row dimension + * + * @var int + * @access private + */ + private $m; + + /** + * Matrix column dimension + * + * @var int + * @access private + */ + private $n; + + + /** + * Polymorphic constructor + * + * As PHP has no support for polymorphic constructors, we hack our own sort of polymorphism using func_num_args, func_get_arg, and gettype. In essence, we're just implementing a simple RTTI filter and calling the appropriate constructor. + */ + public function __construct() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + //Square matrix - n x n + case 'integer': + $this->m = $args[0]; + $this->n = $args[0]; + $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); + break; + //Rectangular matrix - m x n + case 'integer,integer': + $this->m = $args[0]; + $this->n = $args[1]; + $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); + break; + //Rectangular matrix constant-filled - m x n filled with c + case 'integer,integer,integer': + $this->m = $args[0]; + $this->n = $args[1]; + $this->A = array_fill(0, $this->m, array_fill(0, $this->n, $args[2])); + break; + //Rectangular matrix constant-filled - m x n filled with c + case 'integer,integer,double': + $this->m = $args[0]; + $this->n = $args[1]; + $this->A = array_fill(0, $this->m, array_fill(0, $this->n, $args[2])); + break; + //Rectangular matrix - m x n initialized from 2D array + case 'array': + $this->m = count($args[0]); + $this->n = count($args[0][0]); + $this->A = $args[0]; + break; + //Rectangular matrix - m x n initialized from 2D array + case 'array,integer,integer': + $this->m = $args[1]; + $this->n = $args[2]; + $this->A = $args[0]; + break; + //Rectangular matrix - m x n initialized from packed array + case 'array,integer': + $this->m = $args[1]; + if ($this->m != 0) { + $this->n = count($args[0]) / $this->m; + } else { + $this->n = 0; + } + if (($this->m * $this->n) == count($args[0])) { + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = $args[0][$i + $j * $this->m]; + } + } + } else { + throw new Exception(JAMAError(ArrayLengthException)); + } + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function __construct() + + + /** + * getArray + * + * @return array Matrix array + */ + public function getArray() { + return $this->A; + } // function getArray() + + + /** + * getArrayCopy + * + * @return array Matrix array copy + */ + public function getArrayCopy() { + return $this->A; + } // function getArrayCopy() + + + /** + * constructWithCopy + * Construct a matrix from a copy of a 2-D array. + * + * @param double A[][] Two-dimensional array of doubles. + * @exception IllegalArgumentException All rows must have the same length + */ + public function constructWithCopy($A) { + $this->m = count($A); + $this->n = count($A[0]); + $newCopyMatrix = new Matrix($this->m, $this->n); + for ($i = 0; $i < $this->m; ++$i) { + if (count($A[$i]) != $this->n) { + throw new Exception(JAMAError(RowLengthException)); + } + for ($j = 0; $j < $this->n; ++$j) { + $newCopyMatrix->A[$i][$j] = $A[$i][$j]; + } + } + return $newCopyMatrix; + } // function constructWithCopy() + + + /** + * getColumnPackedCopy + * + * Get a column-packed array + * @return array Column-packed matrix array + */ + public function getColumnPackedCopy() { + $P = array(); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + array_push($P, $this->A[$j][$i]); + } + } + return $P; + } // function getColumnPackedCopy() + + + /** + * getRowPackedCopy + * + * Get a row-packed array + * @return array Row-packed matrix array + */ + public function getRowPackedCopy() { + $P = array(); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + array_push($P, $this->A[$i][$j]); + } + } + return $P; + } // function getRowPackedCopy() + + + /** + * getRowDimension + * + * @return int Row dimension + */ + public function getRowDimension() { + return $this->m; + } // function getRowDimension() + + + /** + * getColumnDimension + * + * @return int Column dimension + */ + public function getColumnDimension() { + return $this->n; + } // function getColumnDimension() + + + /** + * get + * + * Get the i,j-th element of the matrix. + * @param int $i Row position + * @param int $j Column position + * @return mixed Element (int/float/double) + */ + public function get($i = null, $j = null) { + return $this->A[$i][$j]; + } // function get() + + + /** + * getMatrix + * + * Get a submatrix + * @param int $i0 Initial row index + * @param int $iF Final row index + * @param int $j0 Initial column index + * @param int $jF Final column index + * @return Matrix Submatrix + */ + public function getMatrix() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + //A($i0...; $j0...) + case 'integer,integer': + list($i0, $j0) = $args; + if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + $R = new Matrix($m, $n); + for($i = $i0; $i < $this->m; ++$i) { + for($j = $j0; $j < $this->n; ++$j) { + $R->set($i, $j, $this->A[$i][$j]); + } + } + return $R; + break; + //A($i0...$iF; $j0...$jF) + case 'integer,integer,integer,integer': + list($i0, $iF, $j0, $jF) = $args; + if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + $R = new Matrix($m+1, $n+1); + for($i = $i0; $i <= $iF; ++$i) { + for($j = $j0; $j <= $jF; ++$j) { + $R->set($i - $i0, $j - $j0, $this->A[$i][$j]); + } + } + return $R; + break; + //$R = array of row indices; $C = array of column indices + case 'array,array': + list($RL, $CL) = $args; + if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + $R = new Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i - $i0, $j - $j0, $this->A[$RL[$i]][$CL[$j]]); + } + } + return $R; + break; + //$RL = array of row indices; $CL = array of column indices + case 'array,array': + list($RL, $CL) = $args; + if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + $R = new Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]); + } + } + return $R; + break; + //A($i0...$iF); $CL = array of column indices + case 'integer,integer,array': + list($i0, $iF, $CL) = $args; + if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + $R = new Matrix($m, $n); + for($i = $i0; $i < $iF; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i - $i0, $j, $this->A[$RL[$i]][$j]); + } + } + return $R; + break; + //$RL = array of row indices + case 'array,integer,integer': + list($RL, $j0, $jF) = $args; + if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + $R = new Matrix($m, $n+1); + for($i = 0; $i < $m; ++$i) { + for($j = $j0; $j <= $jF; ++$j) { + $R->set($i, $j - $j0, $this->A[$RL[$i]][$j]); + } + } + return $R; + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function getMatrix() + + + /** + * setMatrix + * + * Set a submatrix + * @param int $i0 Initial row index + * @param int $j0 Initial column index + * @param mixed $S Matrix/Array submatrix + * ($i0, $j0, $S) $S = Matrix + * ($i0, $j0, $S) $S = Array + */ + public function setMatrix() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'integer,integer,object': + if ($args[2] instanceof Matrix) { $M = $args[2]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + if (($args[0] + $M->m) <= $this->m) { $i0 = $args[0]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (($args[1] + $M->n) <= $this->n) { $j0 = $args[1]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + for($i = $i0; $i < $i0 + $M->m; ++$i) { + for($j = $j0; $j < $j0 + $M->n; ++$j) { + $this->A[$i][$j] = $M->get($i - $i0, $j - $j0); + } + } + break; + case 'integer,integer,array': + $M = new Matrix($args[2]); + if (($args[0] + $M->m) <= $this->m) { $i0 = $args[0]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + if (($args[1] + $M->n) <= $this->n) { $j0 = $args[1]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); } + for($i = $i0; $i < $i0 + $M->m; ++$i) { + for($j = $j0; $j < $j0 + $M->n; ++$j) { + $this->A[$i][$j] = $M->get($i - $i0, $j - $j0); + } + } + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function setMatrix() + + + /** + * checkMatrixDimensions + * + * Is matrix B the same size? + * @param Matrix $B Matrix B + * @return boolean + */ + public function checkMatrixDimensions($B = null) { + if ($B instanceof Matrix) { + if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) { + return true; + } else { + throw new Exception(JAMAError(MatrixDimensionException)); + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function checkMatrixDimensions() + + + + /** + * set + * + * Set the i,j-th element of the matrix. + * @param int $i Row position + * @param int $j Column position + * @param mixed $c Int/float/double value + * @return mixed Element (int/float/double) + */ + public function set($i = null, $j = null, $c = null) { + // Optimized set version just has this + $this->A[$i][$j] = $c; + /* + if (is_int($i) && is_int($j) && is_numeric($c)) { + if (($i < $this->m) && ($j < $this->n)) { + $this->A[$i][$j] = $c; + } else { + echo "A[$i][$j] = $c
"; + throw new Exception(JAMAError(ArgumentBoundsException)); + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + */ + } // function set() + + + /** + * identity + * + * Generate an identity matrix. + * @param int $m Row dimension + * @param int $n Column dimension + * @return Matrix Identity matrix + */ + public function identity($m = null, $n = null) { + return $this->diagonal($m, $n, 1); + } // function identity() + + + /** + * diagonal + * + * Generate a diagonal matrix + * @param int $m Row dimension + * @param int $n Column dimension + * @param mixed $c Diagonal value + * @return Matrix Diagonal matrix + */ + public function diagonal($m = null, $n = null, $c = 1) { + $R = new Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + $R->set($i, $i, $c); + } + return $R; + } // function diagonal() + + + /** + * filled + * + * Generate a filled matrix + * @param int $m Row dimension + * @param int $n Column dimension + * @param int $c Fill constant + * @return Matrix Filled matrix + */ + public function filled($m = null, $n = null, $c = 0) { + if (is_int($m) && is_int($n) && is_numeric($c)) { + $R = new Matrix($m, $n, $c); + return $R; + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function filled() + + /** + * random + * + * Generate a random matrix + * @param int $m Row dimension + * @param int $n Column dimension + * @return Matrix Random matrix + */ + public function random($m = null, $n = null, $a = RAND_MIN, $b = RAND_MAX) { + if (is_int($m) && is_int($n) && is_numeric($a) && is_numeric($b)) { + $R = new Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i, $j, mt_rand($a, $b)); + } + } + return $R; + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function random() + + + /** + * packed + * + * Alias for getRowPacked + * @return array Packed array + */ + public function packed() { + return $this->getRowPacked(); + } // function packed() + + + /** + * getMatrixByRow + * + * Get a submatrix by row index/range + * @param int $i0 Initial row index + * @param int $iF Final row index + * @return Matrix Submatrix + */ + public function getMatrixByRow($i0 = null, $iF = null) { + if (is_int($i0)) { + if (is_int($iF)) { + return $this->getMatrix($i0, 0, $iF + 1, $this->n); + } else { + return $this->getMatrix($i0, 0, $i0 + 1, $this->n); + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function getMatrixByRow() + + + /** + * getMatrixByCol + * + * Get a submatrix by column index/range + * @param int $i0 Initial column index + * @param int $iF Final column index + * @return Matrix Submatrix + */ + public function getMatrixByCol($j0 = null, $jF = null) { + if (is_int($j0)) { + if (is_int($jF)) { + return $this->getMatrix(0, $j0, $this->m, $jF + 1); + } else { + return $this->getMatrix(0, $j0, $this->m, $j0 + 1); + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function getMatrixByCol() + + + /** + * transpose + * + * Tranpose matrix + * @return Matrix Transposed matrix + */ + public function transpose() { + $R = new Matrix($this->n, $this->m); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $R->set($j, $i, $this->A[$i][$j]); + } + } + return $R; + } // function transpose() + + + /** + * norm1 + * + * One norm + * @return float Maximum column sum + */ + public function norm1() { + $r = 0; + for($j = 0; $j < $this->n; ++$j) { + $s = 0; + for($i = 0; $i < $this->m; ++$i) { + $s += abs($this->A[$i][$j]); + } + $r = ($r > $s) ? $r : $s; + } + return $r; + } // function norm1() + + + /** + * norm2 + * + * Maximum singular value + * @return float Maximum singular value + */ + public function norm2() { + } // function norm2() + + + /** + * normInf + * + * Infinite norm + * @return float Maximum row sum + */ + public function normInf() { + $r = 0; + for($i = 0; $i < $this->m; ++$i) { + $s = 0; + for($j = 0; $j < $this->n; ++$j) { + $s += abs($this->A[$i][$j]); + } + $r = ($r > $s) ? $r : $s; + } + return $r; + } // function normInf() + + + /** + * normF + * + * Frobenius norm + * @return float Square root of the sum of all elements squared + */ + public function normF() { + $f = 0; + for ($i = 0; $i < $this->m; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + $f = hypo($f,$this->A[$i][$j]); + } + } + return $f; + } // function normF() + + + /** + * Matrix rank + * + * @return effective numerical rank, obtained from SVD. + */ + public function rank () { + $svd = new SingularValueDecomposition($this); + return $svd->rank(); + } // function rank () + + + /** + * Matrix condition (2 norm) + * + * @return ratio of largest to smallest singular value. + */ + public function cond () { + $svd = new SingularValueDecomposition($this); + return $svd->cond(); + } // function cond () + + + /** + * trace + * + * Sum of diagonal elements + * @return float Sum of diagonal elements + */ + public function trace() { + $s = 0; + $n = min($this->m, $this->n); + for($i = 0; $i < $n; ++$i) { + $s += $this->A[$i][$i]; + } + return $s; + } // function trace() + + + /** + * uminus + * + * Unary minus matrix -A + * @return Matrix Unary minus matrix + */ + public function uminus() { + } // function uminus() + + + /** + * plus + * + * A + B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function plus() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]); + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function plus() + + + /** + * plusEquals + * + * A = A + B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function plusEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] += $M->get($i, $j); + } + } + return $this; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function plusEquals() + + + /** + * minus + * + * A - B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function minus() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]); + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function minus() + + + /** + * minusEquals + * + * A = A - B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function minusEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] -= $M->get($i, $j); + } + } + return $this; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function minusEquals() + + + /** + * arrayTimes + * + * Element-by-element multiplication + * Cij = Aij * Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Cij + */ + public function arrayTimes() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]); + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function arrayTimes() + + + /** + * arrayTimesEquals + * + * Element-by-element multiplication + * Aij = Aij * Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Aij + */ + public function arrayTimesEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] *= $M->get($i, $j); + } + } + return $this; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function arrayTimesEquals() + + + /** + * arrayRightDivide + * + * Element-by-element right division + * A / B + * @param Matrix $B Matrix B + * @return Matrix Division result + */ + public function arrayRightDivide() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $this->A[$i][$j] / $M->get($i, $j)); + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function arrayRightDivide() + + + /** + * arrayRightDivideEquals + * + * Element-by-element right division + * Aij = Aij / Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Aij + */ + public function arrayRightDivideEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j); + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function arrayRightDivideEquals() + + + /** + * arrayLeftDivide + * + * Element-by-element Left division + * A / B + * @param Matrix $B Matrix B + * @return Matrix Division result + */ + public function arrayLeftDivide() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j]); + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function arrayLeftDivide() + + + /** + * arrayLeftDivideEquals + * + * Element-by-element Left division + * Aij = Aij / Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Aij + */ + public function arrayLeftDivideEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j]; + } + } + return $M; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function arrayLeftDivideEquals() + + + /** + * times + * + * Matrix multiplication + * @param mixed $n Matrix/Array/Scalar + * @return Matrix Product + */ + public function times() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $B = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + if ($this->n == $B->m) { + $C = new Matrix($this->m, $B->n); + for($j = 0; $j < $B->n; ++$j) { + for ($k = 0; $k < $this->n; ++$k) { + $Bcolj[$k] = $B->A[$k][$j]; + } + for($i = 0; $i < $this->m; ++$i) { + $Arowi = $this->A[$i]; + $s = 0; + for($k = 0; $k < $this->n; ++$k) { + $s += $Arowi[$k] * $Bcolj[$k]; + } + $C->A[$i][$j] = $s; + } + } + return $C; + } else { + throw new Exception(JAMAError(MatrixDimensionMismatch)); + } + break; + case 'array': + $B = new Matrix($args[0]); + if ($this->n == $B->m) { + $C = new Matrix($this->m, $B->n); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $s = "0"; + for($k = 0; $k < $C->n; ++$k) { + $s += $this->A[$i][$k] * $B->A[$k][$j]; + } + $C->A[$i][$j] = $s; + } + } + return $C; + } else { + throw new Exception(JAMAError(MatrixDimensionMismatch)); + } + return $M; + break; + case 'integer': + $C = new Matrix($this->A); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $C->A[$i][$j] *= $args[0]; + } + } + return $C; + break; + case 'double': + $C = new Matrix($this->m, $this->n); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $C->A[$i][$j] = $args[0] * $this->A[$i][$j]; + } + } + return $C; + break; + case 'float': + $C = new Matrix($this->A); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $C->A[$i][$j] *= $args[0]; + } + } + return $C; + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + } else { + throw new Exception(PolymorphicArgumentException); + } + } // function times() + + + /** + * power + * + * A = A ^ B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function power() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + break; + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = pow($this->A[$i][$j],$M->get($i, $j)); + } + } + return $this; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function power() + + + /** + * concat + * + * A = A & B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function concat() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); } + case 'array': + $M = new Matrix($args[0]); + break; + default: + throw new Exception(JAMAError(PolymorphicArgumentException)); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { +// $this->A[$i][$j] = '"'.trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"').'"'; + $this->A[$i][$j] = trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"'); + } + } + return $this; + } else { + throw new Exception(JAMAError(PolymorphicArgumentException)); + } + } // function concat() + + + /** + * chol + * + * Cholesky decomposition + * @return Matrix Cholesky decomposition + */ + public function chol() { + return new CholeskyDecomposition($this); + } // function chol() + + + /** + * lu + * + * LU decomposition + * @return Matrix LU decomposition + */ + public function lu() { + return new LUDecomposition($this); + } // function lu() + + + /** + * qr + * + * QR decomposition + * @return Matrix QR decomposition + */ + public function qr() { + return new QRDecomposition($this); + } // function qr() + + + /** + * eig + * + * Eigenvalue decomposition + * @return Matrix Eigenvalue decomposition + */ + public function eig() { + return new EigenvalueDecomposition($this); + } // function eig() + + + /** + * svd + * + * Singular value decomposition + * @return Singular value decomposition + */ + public function svd() { + return new SingularValueDecomposition($this); + } // function svd() + + + /** + * Solve A*X = B. + * + * @param Matrix $B Right hand side + * @return Matrix ... Solution if A is square, least squares solution otherwise + */ + public function solve($B) { + if ($this->m == $this->n) { + $LU = new LUDecomposition($this); + return $LU->solve($B); + } else { + $QR = new QRDecomposition($this); + return $QR->solve($B); + } + } // function solve() + + + /** + * Matrix inverse or pseudoinverse. + * + * @return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise. + */ + public function inverse() { + return $this->solve($this->identity($this->m, $this->m)); + } // function inverse() + + + /** + * det + * + * Calculate determinant + * @return float Determinant + */ + public function det() { + $L = new LUDecomposition($this); + return $L->det(); + } // function det() + + + /** + * Older debugging utility for backwards compatability. + * + * @return html version of matrix + */ + public function mprint($A, $format="%01.2f", $width=2) { + $m = count($A); + $n = count($A[0]); + $spacing = str_repeat(' ',$width); + + for ($i = 0; $i < $m; ++$i) { + for ($j = 0; $j < $n; ++$j) { + $formatted = sprintf($format, $A[$i][$j]); + echo $formatted.$spacing; + } + echo "
"; + } + } // function mprint() + + + /** + * Debugging utility. + * + * @return Output HTML representation of matrix + */ + public function toHTML($width=2) { + print(''); + for($i = 0; $i < $this->m; ++$i) { + print(''); + for($j = 0; $j < $this->n; ++$j) { + print(''); + } + print(''); + } + print('
' . $this->A[$i][$j] . '
'); + } // function toHTML() + +} // class Matrix diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/QRDecomposition.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/QRDecomposition.php index f86b4e0f8..80680594d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/QRDecomposition.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/QRDecomposition.php @@ -1,195 +1,232 @@ = n, the QR decomposition is an m-by-n -* orthogonal matrix Q and an n-by-n upper triangular matrix R so that -* A = Q*R. -* -* The QR decompostion always exists, even if the matrix does not have -* full rank, so the constructor will never fail. The primary use of the -* QR decomposition is in the least squares solution of nonsquare systems -* of simultaneous linear equations. This will fail if isFullRank() -* returns false. -* -* @author Paul Meagher -* @license PHP v3.0 -* @version 1.1 -*/ +/** + * @package JAMA + * + * For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n + * orthogonal matrix Q and an n-by-n upper triangular matrix R so that + * A = Q*R. + * + * The QR decompostion always exists, even if the matrix does not have + * full rank, so the constructor will never fail. The primary use of the + * QR decomposition is in the least squares solution of nonsquare systems + * of simultaneous linear equations. This will fail if isFullRank() + * returns false. + * + * @author Paul Meagher + * @license PHP v3.0 + * @version 1.1 + */ class QRDecomposition { - /** - * Array for internal storage of decomposition. - * @var array - */ - var $QR = array(); - /** - * Row dimension. - * @var integer - */ - var $m; + /** + * Array for internal storage of decomposition. + * @var array + */ + private $QR = array(); - /** - * Column dimension. - * @var integer - */ - var $n; + /** + * Row dimension. + * @var integer + */ + private $m; - /** - * Array for internal storage of diagonal of R. - * @var array - */ - var $Rdiag = array(); + /** + * Column dimension. + * @var integer + */ + private $n; - /** - * QR Decomposition computed by Householder reflections. - * @param matrix $A Rectangular matrix - * @return Structure to access R and the Householder vectors and compute Q. - */ - function QRDecomposition($A) { - if( is_a($A, 'Matrix') ) { - // Initialize. - $this->QR = $A->getArrayCopy(); - $this->m = $A->getRowDimension(); - $this->n = $A->getColumnDimension(); - // Main loop. - for ($k = 0; $k < $this->n; $k++) { - // Compute 2-norm of k-th column without under/overflow. - $nrm = 0.0; - for ($i = $k; $i < $this->m; $i++) - $nrm = hypo($nrm, $this->QR[$i][$k]); - if ($nrm != 0.0) { - // Form k-th Householder vector. - if ($this->QR[$k][$k] < 0) - $nrm = -$nrm; - for ($i = $k; $i < $this->m; $i++) - $this->QR[$i][$k] /= $nrm; - $this->QR[$k][$k] += 1.0; - // Apply transformation to remaining columns. - for ($j = $k+1; $j < $this->n; $j++) { - $s = 0.0; - for ($i = $k; $i < $this->m; $i++) - $s += $this->QR[$i][$k] * $this->QR[$i][$j]; - $s = -$s/$this->QR[$k][$k]; - for ($i = $k; $i < $this->m; $i++) - $this->QR[$i][$j] += $s * $this->QR[$i][$k]; - } - } - $this->Rdiag[$k] = -$nrm; - } - } else - trigger_error(ArgumentTypeException, ERROR); - } + /** + * Array for internal storage of diagonal of R. + * @var array + */ + private $Rdiag = array(); - /** - * Is the matrix full rank? - * @return boolean true if R, and hence A, has full rank, else false. - */ - function isFullRank() { - for ($j = 0; $j < $this->n; $j++) - if ($this->Rdiag[$j] == 0) - return false; - return true; - } - /** - * Return the Householder vectors - * @return Matrix Lower trapezoidal matrix whose columns define the reflections - */ - function getH() { - for ($i = 0; $i < $this->m; $i++) { - for ($j = 0; $j < $this->n; $j++) { - if ($i >= $j) - $H[$i][$j] = $this->QR[$i][$j]; - else - $H[$i][$j] = 0.0; - } - } - return new Matrix($H); - } + /** + * QR Decomposition computed by Householder reflections. + * + * @param matrix $A Rectangular matrix + * @return Structure to access R and the Householder vectors and compute Q. + */ + public function __construct($A) { + if($A instanceof Matrix) { + // Initialize. + $this->QR = $A->getArrayCopy(); + $this->m = $A->getRowDimension(); + $this->n = $A->getColumnDimension(); + // Main loop. + for ($k = 0; $k < $this->n; ++$k) { + // Compute 2-norm of k-th column without under/overflow. + $nrm = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $nrm = hypo($nrm, $this->QR[$i][$k]); + } + if ($nrm != 0.0) { + // Form k-th Householder vector. + if ($this->QR[$k][$k] < 0) { + $nrm = -$nrm; + } + for ($i = $k; $i < $this->m; ++$i) { + $this->QR[$i][$k] /= $nrm; + } + $this->QR[$k][$k] += 1.0; + // Apply transformation to remaining columns. + for ($j = $k+1; $j < $this->n; ++$j) { + $s = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $s += $this->QR[$i][$k] * $this->QR[$i][$j]; + } + $s = -$s/$this->QR[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $this->QR[$i][$j] += $s * $this->QR[$i][$k]; + } + } + } + $this->Rdiag[$k] = -$nrm; + } + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } // function __construct() - /** - * Return the upper triangular factor - * @return Matrix upper triangular factor - */ - function getR() { - for ($i = 0; $i < $this->n; $i++) { - for ($j = 0; $j < $this->n; $j++) { - if ($i < $j) - $R[$i][$j] = $this->QR[$i][$j]; - else if ($i == $j) - $R[$i][$j] = $this->Rdiag[$i]; - else - $R[$i][$j] = 0.0; - } - } - return new Matrix($R); - } - /** - * Generate and return the (economy-sized) orthogonal factor - * @return Matrix orthogonal factor - */ - function getQ() { - for ($k = $this->n-1; $k >= 0; $k--) { - for ($i = 0; $i < $this->m; $i++) - $Q[$i][$k] = 0.0; - $Q[$k][$k] = 1.0; - for ($j = $k; $j < $this->n; $j++) { - if ($this->QR[$k][$k] != 0) { - $s = 0.0; - for ($i = $k; $i < $this->m; $i++) - $s += $this->QR[$i][$k] * $Q[$i][$j]; - $s = -$s/$this->QR[$k][$k]; - for ($i = $k; $i < $this->m; $i++) - $Q[$i][$j] += $s * $this->QR[$i][$k]; - } - } - } - /* - for( $i = 0; $i < count($Q); $i++ ) - for( $j = 0; $j < count($Q); $j++ ) - if(! isset($Q[$i][$j]) ) - $Q[$i][$j] = 0; - */ - return new Matrix($Q); - } - - /** - * Least squares solution of A*X = B - * @param Matrix $B A Matrix with as many rows as A and any number of columns. - * @return Matrix Matrix that minimizes the two norm of Q*R*X-B. - */ - function solve($B) { - if ($B->getRowDimension() == $this->m) { - if ($this->isFullRank()) { - // Copy right hand side - $nx = $B->getColumnDimension(); - $X = $B->getArrayCopy(); - // Compute Y = transpose(Q)*B - for ($k = 0; $k < $this->n; $k++) { - for ($j = 0; $j < $nx; $j++) { - $s = 0.0; - for ($i = $k; $i < $this->m; $i++) - $s += $this->QR[$i][$k] * $X[$i][$j]; - $s = -$s/$this->QR[$k][$k]; - for ($i = $k; $i < $this->m; $i++) - $X[$i][$j] += $s * $this->QR[$i][$k]; - } - } - // Solve R*X = Y; - for ($k = $this->n-1; $k >= 0; $k--) { - for ($j = 0; $j < $nx; $j++) - $X[$k][$j] /= $this->Rdiag[$k]; - for ($i = 0; $i < $k; $i++) - for ($j = 0; $j < $nx; $j++) - $X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k]; - } - $X = new Matrix($X); - return ($X->getMatrix(0, $this->n-1, 0, $nx)); - } else - trigger_error(MatrixRankException, ERROR); - } else - trigger_error(MatrixDimensionException, ERROR); - } -} + /** + * Is the matrix full rank? + * + * @return boolean true if R, and hence A, has full rank, else false. + */ + public function isFullRank() { + for ($j = 0; $j < $this->n; ++$j) { + if ($this->Rdiag[$j] == 0) { + return false; + } + } + return true; + } // function isFullRank() + + + /** + * Return the Householder vectors + * + * @return Matrix Lower trapezoidal matrix whose columns define the reflections + */ + public function getH() { + for ($i = 0; $i < $this->m; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i >= $j) { + $H[$i][$j] = $this->QR[$i][$j]; + } else { + $H[$i][$j] = 0.0; + } + } + } + return new Matrix($H); + } // function getH() + + + /** + * Return the upper triangular factor + * + * @return Matrix upper triangular factor + */ + public function getR() { + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i < $j) { + $R[$i][$j] = $this->QR[$i][$j]; + } elseif ($i == $j) { + $R[$i][$j] = $this->Rdiag[$i]; + } else { + $R[$i][$j] = 0.0; + } + } + } + return new Matrix($R); + } // function getR() + + + /** + * Generate and return the (economy-sized) orthogonal factor + * + * @return Matrix orthogonal factor + */ + public function getQ() { + for ($k = $this->n-1; $k >= 0; --$k) { + for ($i = 0; $i < $this->m; ++$i) { + $Q[$i][$k] = 0.0; + } + $Q[$k][$k] = 1.0; + for ($j = $k; $j < $this->n; ++$j) { + if ($this->QR[$k][$k] != 0) { + $s = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $s += $this->QR[$i][$k] * $Q[$i][$j]; + } + $s = -$s/$this->QR[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $Q[$i][$j] += $s * $this->QR[$i][$k]; + } + } + } + } + /* + for($i = 0; $i < count($Q); ++$i) { + for($j = 0; $j < count($Q); ++$j) { + if(! isset($Q[$i][$j]) ) { + $Q[$i][$j] = 0; + } + } + } + */ + return new Matrix($Q); + } // function getQ() + + + /** + * Least squares solution of A*X = B + * + * @param Matrix $B A Matrix with as many rows as A and any number of columns. + * @return Matrix Matrix that minimizes the two norm of Q*R*X-B. + */ + public function solve($B) { + if ($B->getRowDimension() == $this->m) { + if ($this->isFullRank()) { + // Copy right hand side + $nx = $B->getColumnDimension(); + $X = $B->getArrayCopy(); + // Compute Y = transpose(Q)*B + for ($k = 0; $k < $this->n; ++$k) { + for ($j = 0; $j < $nx; ++$j) { + $s = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $s += $this->QR[$i][$k] * $X[$i][$j]; + } + $s = -$s/$this->QR[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $X[$i][$j] += $s * $this->QR[$i][$k]; + } + } + } + // Solve R*X = Y; + for ($k = $this->n-1; $k >= 0; --$k) { + for ($j = 0; $j < $nx; ++$j) { + $X[$k][$j] /= $this->Rdiag[$k]; + } + for ($i = 0; $i < $k; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k]; + } + } + } + $X = new Matrix($X); + return ($X->getMatrix(0, $this->n-1, 0, $nx)); + } else { + throw new Exception(JAMAError(MatrixRankException)); + } + } else { + throw new Exception(JAMAError(MatrixDimensionException)); + } + } // function solve() + +} // class QRDecomposition diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php index 4fec7116f..a4b096c59 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php @@ -1,501 +1,526 @@ = n, the singular value decomposition is -* an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and -* an n-by-n orthogonal matrix V so that A = U*S*V'. -* -* The singular values, sigma[$k] = S[$k][$k], are ordered so that -* sigma[0] >= sigma[1] >= ... >= sigma[n-1]. -* -* The singular value decompostion always exists, so the constructor will -* never fail. The matrix condition number and the effective numerical -* rank can be computed from this decomposition. -* -* @author Paul Meagher -* @license PHP v3.0 -* @version 1.1 -*/ + * @package JAMA + * + * For an m-by-n matrix A with m >= n, the singular value decomposition is + * an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and + * an n-by-n orthogonal matrix V so that A = U*S*V'. + * + * The singular values, sigma[$k] = S[$k][$k], are ordered so that + * sigma[0] >= sigma[1] >= ... >= sigma[n-1]. + * + * The singular value decompostion always exists, so the constructor will + * never fail. The matrix condition number and the effective numerical + * rank can be computed from this decomposition. + * + * @author Paul Meagher + * @license PHP v3.0 + * @version 1.1 + */ class SingularValueDecomposition { - /** - * Internal storage of U. - * @var array - */ - var $U = array(); + /** + * Internal storage of U. + * @var array + */ + private $U = array(); - /** - * Internal storage of V. - * @var array - */ - var $V = array(); + /** + * Internal storage of V. + * @var array + */ + private $V = array(); - /** - * Internal storage of singular values. - * @var array - */ - var $s = array(); + /** + * Internal storage of singular values. + * @var array + */ + private $s = array(); - /** - * Row dimension. - * @var int - */ - var $m; + /** + * Row dimension. + * @var int + */ + private $m; - /** - * Column dimension. - * @var int - */ - var $n; + /** + * Column dimension. + * @var int + */ + private $n; - /** - * Construct the singular value decomposition - * - * Derived from LINPACK code. - * - * @param $A Rectangular matrix - * @return Structure to access U, S and V. - */ - function SingularValueDecomposition ($Arg) { - // Initialize. + /** + * Construct the singular value decomposition + * + * Derived from LINPACK code. + * + * @param $A Rectangular matrix + * @return Structure to access U, S and V. + */ + public function __construct($Arg) { - $A = $Arg->getArrayCopy(); - $this->m = $Arg->getRowDimension(); - $this->n = $Arg->getColumnDimension(); - $nu = min($this->m, $this->n); - $e = array(); - $work = array(); - $wantu = true; - $wantv = true; - $nct = min($this->m - 1, $this->n); - $nrt = max(0, min($this->n - 2, $this->m)); + // Initialize. + $A = $Arg->getArrayCopy(); + $this->m = $Arg->getRowDimension(); + $this->n = $Arg->getColumnDimension(); + $nu = min($this->m, $this->n); + $e = array(); + $work = array(); + $wantu = true; + $wantv = true; + $nct = min($this->m - 1, $this->n); + $nrt = max(0, min($this->n - 2, $this->m)); - // Reduce A to bidiagonal form, storing the diagonal elements - // in s and the super-diagonal elements in e. + // Reduce A to bidiagonal form, storing the diagonal elements + // in s and the super-diagonal elements in e. + for ($k = 0; $k < max($nct,$nrt); ++$k) { - for ($k = 0; $k < max($nct,$nrt); $k++) { + if ($k < $nct) { + // Compute the transformation for the k-th column and + // place the k-th diagonal in s[$k]. + // Compute 2-norm of k-th column without under/overflow. + $this->s[$k] = 0; + for ($i = $k; $i < $this->m; ++$i) { + $this->s[$k] = hypo($this->s[$k], $A[$i][$k]); + } + if ($this->s[$k] != 0.0) { + if ($A[$k][$k] < 0.0) { + $this->s[$k] = -$this->s[$k]; + } + for ($i = $k; $i < $this->m; ++$i) { + $A[$i][$k] /= $this->s[$k]; + } + $A[$k][$k] += 1.0; + } + $this->s[$k] = -$this->s[$k]; + } - if ($k < $nct) { - // Compute the transformation for the k-th column and - // place the k-th diagonal in s[$k]. - // Compute 2-norm of k-th column without under/overflow. - $this->s[$k] = 0; - for ($i = $k; $i < $this->m; $i++) - $this->s[$k] = hypo($this->s[$k], $A[$i][$k]); - if ($this->s[$k] != 0.0) { - if ($A[$k][$k] < 0.0) - $this->s[$k] = -$this->s[$k]; - for ($i = $k; $i < $this->m; $i++) - $A[$i][$k] /= $this->s[$k]; - $A[$k][$k] += 1.0; - } - $this->s[$k] = -$this->s[$k]; - } + for ($j = $k + 1; $j < $this->n; ++$j) { + if (($k < $nct) & ($this->s[$k] != 0.0)) { + // Apply the transformation. + $t = 0; + for ($i = $k; $i < $this->m; ++$i) { + $t += $A[$i][$k] * $A[$i][$j]; + } + $t = -$t / $A[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $A[$i][$j] += $t * $A[$i][$k]; + } + // Place the k-th row of A into e for the + // subsequent calculation of the row transformation. + $e[$j] = $A[$k][$j]; + } + } - for ($j = $k + 1; $j < $this->n; $j++) { - if (($k < $nct) & ($this->s[$k] != 0.0)) { - // Apply the transformation. - $t = 0; - for ($i = $k; $i < $this->m; $i++) - $t += $A[$i][$k] * $A[$i][$j]; - $t = -$t / $A[$k][$k]; - for ($i = $k; $i < $this->m; $i++) - $A[$i][$j] += $t * $A[$i][$k]; - // Place the k-th row of A into e for the - // subsequent calculation of the row transformation. - $e[$j] = $A[$k][$j]; - } - } + if ($wantu AND ($k < $nct)) { + // Place the transformation in U for subsequent back + // multiplication. + for ($i = $k; $i < $this->m; ++$i) { + $this->U[$i][$k] = $A[$i][$k]; + } + } - if ($wantu AND ($k < $nct)) { - // Place the transformation in U for subsequent back - // multiplication. - for ($i = $k; $i < $this->m; $i++) - $this->U[$i][$k] = $A[$i][$k]; - } + if ($k < $nrt) { + // Compute the k-th row transformation and place the + // k-th super-diagonal in e[$k]. + // Compute 2-norm without under/overflow. + $e[$k] = 0; + for ($i = $k + 1; $i < $this->n; ++$i) { + $e[$k] = hypo($e[$k], $e[$i]); + } + if ($e[$k] != 0.0) { + if ($e[$k+1] < 0.0) { + $e[$k] = -$e[$k]; + } + for ($i = $k + 1; $i < $this->n; ++$i) { + $e[$i] /= $e[$k]; + } + $e[$k+1] += 1.0; + } + $e[$k] = -$e[$k]; + if (($k+1 < $this->m) AND ($e[$k] != 0.0)) { + // Apply the transformation. + for ($i = $k+1; $i < $this->m; ++$i) { + $work[$i] = 0.0; + } + for ($j = $k+1; $j < $this->n; ++$j) { + for ($i = $k+1; $i < $this->m; ++$i) { + $work[$i] += $e[$j] * $A[$i][$j]; + } + } + for ($j = $k + 1; $j < $this->n; ++$j) { + $t = -$e[$j] / $e[$k+1]; + for ($i = $k + 1; $i < $this->m; ++$i) { + $A[$i][$j] += $t * $work[$i]; + } + } + } + if ($wantv) { + // Place the transformation in V for subsequent + // back multiplication. + for ($i = $k + 1; $i < $this->n; ++$i) { + $this->V[$i][$k] = $e[$i]; + } + } + } + } - if ($k < $nrt) { - // Compute the k-th row transformation and place the - // k-th super-diagonal in e[$k]. - // Compute 2-norm without under/overflow. - $e[$k] = 0; - for ($i = $k + 1; $i < $this->n; $i++) - $e[$k] = hypo($e[$k], $e[$i]); - if ($e[$k] != 0.0) { - if ($e[$k+1] < 0.0) - $e[$k] = -$e[$k]; - for ($i = $k + 1; $i < $this->n; $i++) - $e[$i] /= $e[$k]; - $e[$k+1] += 1.0; - } - $e[$k] = -$e[$k]; - if (($k+1 < $this->m) AND ($e[$k] != 0.0)) { - // Apply the transformation. - for ($i = $k+1; $i < $this->m; $i++) - $work[$i] = 0.0; - for ($j = $k+1; $j < $this->n; $j++) - for ($i = $k+1; $i < $this->m; $i++) - $work[$i] += $e[$j] * $A[$i][$j]; - for ($j = $k + 1; $j < $this->n; $j++) { - $t = -$e[$j] / $e[$k+1]; - for ($i = $k + 1; $i < $this->m; $i++) - $A[$i][$j] += $t * $work[$i]; - } - } - if ($wantv) { - // Place the transformation in V for subsequent - // back multiplication. - for ($i = $k + 1; $i < $this->n; $i++) - $this->V[$i][$k] = $e[$i]; - } - } - } - - // Set up the final bidiagonal matrix or order p. - $p = min($this->n, $this->m + 1); - if ($nct < $this->n) - $this->s[$nct] = $A[$nct][$nct]; - if ($this->m < $p) - $this->s[$p-1] = 0.0; - if ($nrt + 1 < $p) - $e[$nrt] = $A[$nrt][$p-1]; - $e[$p-1] = 0.0; - // If required, generate U. - if ($wantu) { - for ($j = $nct; $j < $nu; $j++) { - for ($i = 0; $i < $this->m; $i++) - $this->U[$i][$j] = 0.0; - $this->U[$j][$j] = 1.0; - } - for ($k = $nct - 1; $k >= 0; $k--) { - if ($this->s[$k] != 0.0) { - for ($j = $k + 1; $j < $nu; $j++) { - $t = 0; - for ($i = $k; $i < $this->m; $i++) - $t += $this->U[$i][$k] * $this->U[$i][$j]; - $t = -$t / $this->U[$k][$k]; - for ($i = $k; $i < $this->m; $i++) - $this->U[$i][$j] += $t * $this->U[$i][$k]; - } - for ($i = $k; $i < $this->m; $i++ ) - $this->U[$i][$k] = -$this->U[$i][$k]; - $this->U[$k][$k] = 1.0 + $this->U[$k][$k]; - for ($i = 0; $i < $k - 1; $i++) - $this->U[$i][$k] = 0.0; - } else { - for ($i = 0; $i < $this->m; $i++) - $this->U[$i][$k] = 0.0; - $this->U[$k][$k] = 1.0; - } - } - } + // Set up the final bidiagonal matrix or order p. + $p = min($this->n, $this->m + 1); + if ($nct < $this->n) { + $this->s[$nct] = $A[$nct][$nct]; + } + if ($this->m < $p) { + $this->s[$p-1] = 0.0; + } + if ($nrt + 1 < $p) { + $e[$nrt] = $A[$nrt][$p-1]; + } + $e[$p-1] = 0.0; + // If required, generate U. + if ($wantu) { + for ($j = $nct; $j < $nu; ++$j) { + for ($i = 0; $i < $this->m; ++$i) { + $this->U[$i][$j] = 0.0; + } + $this->U[$j][$j] = 1.0; + } + for ($k = $nct - 1; $k >= 0; --$k) { + if ($this->s[$k] != 0.0) { + for ($j = $k + 1; $j < $nu; ++$j) { + $t = 0; + for ($i = $k; $i < $this->m; ++$i) { + $t += $this->U[$i][$k] * $this->U[$i][$j]; + } + $t = -$t / $this->U[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $this->U[$i][$j] += $t * $this->U[$i][$k]; + } + } + for ($i = $k; $i < $this->m; ++$i ) { + $this->U[$i][$k] = -$this->U[$i][$k]; + } + $this->U[$k][$k] = 1.0 + $this->U[$k][$k]; + for ($i = 0; $i < $k - 1; ++$i) { + $this->U[$i][$k] = 0.0; + } + } else { + for ($i = 0; $i < $this->m; ++$i) { + $this->U[$i][$k] = 0.0; + } + $this->U[$k][$k] = 1.0; + } + } + } - // If required, generate V. - if ($wantv) { - for ($k = $this->n - 1; $k >= 0; $k--) { - if (($k < $nrt) AND ($e[$k] != 0.0)) { - for ($j = $k + 1; $j < $nu; $j++) { - $t = 0; - for ($i = $k + 1; $i < $this->n; $i++) - $t += $this->V[$i][$k]* $this->V[$i][$j]; - $t = -$t / $this->V[$k+1][$k]; - for ($i = $k + 1; $i < $this->n; $i++) - $this->V[$i][$j] += $t * $this->V[$i][$k]; - } - } - for ($i = 0; $i < $this->n; $i++) - $this->V[$i][$k] = 0.0; - $this->V[$k][$k] = 1.0; - } - } - - // Main iteration loop for the singular values. - $pp = $p - 1; - $iter = 0; - $eps = pow(2.0, -52.0); - while ($p > 0) { - - // Here is where a test for too many iterations would go. - // This section of the program inspects for negligible - // elements in the s and e arrays. On completion the - // variables kase and k are set as follows: - // kase = 1 if s(p) and e[k-1] are negligible and k

n - 1; $k >= 0; --$k) { + if (($k < $nrt) AND ($e[$k] != 0.0)) { + for ($j = $k + 1; $j < $nu; ++$j) { + $t = 0; + for ($i = $k + 1; $i < $this->n; ++$i) { + $t += $this->V[$i][$k]* $this->V[$i][$j]; + } + $t = -$t / $this->V[$k+1][$k]; + for ($i = $k + 1; $i < $this->n; ++$i) { + $this->V[$i][$j] += $t * $this->V[$i][$k]; + } + } + } + for ($i = 0; $i < $this->n; ++$i) { + $this->V[$i][$k] = 0.0; + } + $this->V[$k][$k] = 1.0; + } + } - for ($k = $p - 2; $k >= -1; $k--) { - if ($k == -1) - break; - if (abs($e[$k]) <= $eps * (abs($this->s[$k]) + abs($this->s[$k+1]))) { - $e[$k] = 0.0; - break; - } - } - if ($k == $p - 2) - $kase = 4; - else { - for ($ks = $p - 1; $ks >= $k; $ks--) { - if ($ks == $k) - break; - $t = ($ks != $p ? abs($e[$ks]) : 0.) + ($ks != $k + 1 ? abs($e[$ks-1]) : 0.); - if (abs($this->s[$ks]) <= $eps * $t) { - $this->s[$ks] = 0.0; - break; - } - } - if ($ks == $k) - $kase = 3; - else if ($ks == $p-1) - $kase = 1; - else { - $kase = 2; - $k = $ks; - } - } - $k++; + // Main iteration loop for the singular values. + $pp = $p - 1; + $iter = 0; + $eps = pow(2.0, -52.0); - // Perform the task indicated by kase. - switch ($kase) { - // Deflate negligible s(p). - case 1: - $f = $e[$p-2]; - $e[$p-2] = 0.0; - for ($j = $p - 2; $j >= $k; $j--) { - $t = hypo($this->s[$j],$f); - $cs = $this->s[$j] / $t; - $sn = $f / $t; - $this->s[$j] = $t; - if ($j != $k) { - $f = -$sn * $e[$j-1]; - $e[$j-1] = $cs * $e[$j-1]; - } - if ($wantv) { - for ($i = 0; $i < $this->n; $i++) { - $t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$p-1]; - $this->V[$i][$p-1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$p-1]; - $this->V[$i][$j] = $t; - } - } - } - break; - // Split at negligible s(k). - case 2: - $f = $e[$k-1]; - $e[$k-1] = 0.0; - for ($j = $k; $j < $p; $j++) { - $t = hypo($this->s[$j], $f); - $cs = $this->s[$j] / $t; - $sn = $f / $t; - $this->s[$j] = $t; - $f = -$sn * $e[$j]; - $e[$j] = $cs * $e[$j]; - if ($wantu) { - for ($i = 0; $i < $this->m; $i++) { - $t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$k-1]; - $this->U[$i][$k-1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$k-1]; - $this->U[$i][$j] = $t; - } - } - } - break; - // Perform one qr step. - case 3: - // Calculate the shift. - $scale = max(max(max(max( - abs($this->s[$p-1]),abs($this->s[$p-2])),abs($e[$p-2])), - abs($this->s[$k])), abs($e[$k])); - $sp = $this->s[$p-1] / $scale; - $spm1 = $this->s[$p-2] / $scale; - $epm1 = $e[$p-2] / $scale; - $sk = $this->s[$k] / $scale; - $ek = $e[$k] / $scale; - $b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0; - $c = ($sp * $epm1) * ($sp * $epm1); - $shift = 0.0; - if (($b != 0.0) || ($c != 0.0)) { - $shift = sqrt($b * $b + $c); - if ($b < 0.0) - $shift = -$shift; - $shift = $c / ($b + $shift); - } - $f = ($sk + $sp) * ($sk - $sp) + $shift; - $g = $sk * $ek; - // Chase zeros. - for ($j = $k; $j < $p-1; $j++) { - $t = hypo($f,$g); - $cs = $f/$t; - $sn = $g/$t; - if ($j != $k) - $e[$j-1] = $t; - $f = $cs * $this->s[$j] + $sn * $e[$j]; - $e[$j] = $cs * $e[$j] - $sn * $this->s[$j]; - $g = $sn * $this->s[$j+1]; - $this->s[$j+1] = $cs * $this->s[$j+1]; - if ($wantv) { - for ($i = 0; $i < $this->n; $i++) { - $t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$j+1]; - $this->V[$i][$j+1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$j+1]; - $this->V[$i][$j] = $t; - } - } - $t = hypo($f,$g); - $cs = $f/$t; - $sn = $g/$t; - $this->s[$j] = $t; - $f = $cs * $e[$j] + $sn * $this->s[$j+1]; - $this->s[$j+1] = -$sn * $e[$j] + $cs * $this->s[$j+1]; - $g = $sn * $e[$j+1]; - $e[$j+1] = $cs * $e[$j+1]; - if ($wantu && ($j < $this->m - 1)) { - for ($i = 0; $i < $this->m; $i++) { - $t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$j+1]; - $this->U[$i][$j+1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$j+1]; - $this->U[$i][$j] = $t; - } - } - } - $e[$p-2] = $f; - $iter = $iter + 1; - break; - // Convergence. - case 4: - // Make the singular values positive. - if ($this->s[$k] <= 0.0) { - $this->s[$k] = ($this->s[$k] < 0.0 ? -$this->s[$k] : 0.0); - if ($wantv) { - for ($i = 0; $i <= $pp; $i++) - $this->V[$i][$k] = -$this->V[$i][$k]; - } - } - // Order the singular values. - while ($k < $pp) { - if ($this->s[$k] >= $this->s[$k+1]) - break; - $t = $this->s[$k]; - $this->s[$k] = $this->s[$k+1]; - $this->s[$k+1] = $t; - if ($wantv AND ($k < $this->n - 1)) { - for ($i = 0; $i < $this->n; $i++) { - $t = $this->V[$i][$k+1]; - $this->V[$i][$k+1] = $this->V[$i][$k]; - $this->V[$i][$k] = $t; - } - } - if ($wantu AND ($k < $this->m-1)) { - for ($i = 0; $i < $this->m; $i++) { - $t = $this->U[$i][$k+1]; - $this->U[$i][$k+1] = $this->U[$i][$k]; - $this->U[$i][$k] = $t; - } - } - $k++; - } - $iter = 0; - $p--; - break; - } // end switch - } // end while + while ($p > 0) { + // Here is where a test for too many iterations would go. + // This section of the program inspects for negligible + // elements in the s and e arrays. On completion the + // variables kase and k are set as follows: + // kase = 1 if s(p) and e[k-1] are negligible and k

= -1; --$k) { + if ($k == -1) { + break; + } + if (abs($e[$k]) <= $eps * (abs($this->s[$k]) + abs($this->s[$k+1]))) { + $e[$k] = 0.0; + break; + } + } + if ($k == $p - 2) { + $kase = 4; + } else { + for ($ks = $p - 1; $ks >= $k; --$ks) { + if ($ks == $k) { + break; + } + $t = ($ks != $p ? abs($e[$ks]) : 0.) + ($ks != $k + 1 ? abs($e[$ks-1]) : 0.); + if (abs($this->s[$ks]) <= $eps * $t) { + $this->s[$ks] = 0.0; + break; + } + } + if ($ks == $k) { + $kase = 3; + } else if ($ks == $p-1) { + $kase = 1; + } else { + $kase = 2; + $k = $ks; + } + } + ++$k; - /* - echo "

Output A

"; - $A = new Matrix($A); - $A->toHTML(); - - echo "

Matrix U

"; - echo "
";
-    print_r($this->U);        
-    echo "
"; - - echo "

Matrix V

"; - echo "
";
-    print_r($this->V);        
-    echo "
"; - - echo "

Vector S

"; - echo "
";
-    print_r($this->s);        
-    echo "
"; - exit; - */ - - } // end constructor - - /** - * Return the left singular vectors - * @access public - * @return U - */ - function getU() { - return new Matrix($this->U, $this->m, min($this->m + 1, $this->n)); - } + // Perform the task indicated by kase. + switch ($kase) { + // Deflate negligible s(p). + case 1: + $f = $e[$p-2]; + $e[$p-2] = 0.0; + for ($j = $p - 2; $j >= $k; --$j) { + $t = hypo($this->s[$j],$f); + $cs = $this->s[$j] / $t; + $sn = $f / $t; + $this->s[$j] = $t; + if ($j != $k) { + $f = -$sn * $e[$j-1]; + $e[$j-1] = $cs * $e[$j-1]; + } + if ($wantv) { + for ($i = 0; $i < $this->n; ++$i) { + $t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$p-1]; + $this->V[$i][$p-1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$p-1]; + $this->V[$i][$j] = $t; + } + } + } + break; + // Split at negligible s(k). + case 2: + $f = $e[$k-1]; + $e[$k-1] = 0.0; + for ($j = $k; $j < $p; ++$j) { + $t = hypo($this->s[$j], $f); + $cs = $this->s[$j] / $t; + $sn = $f / $t; + $this->s[$j] = $t; + $f = -$sn * $e[$j]; + $e[$j] = $cs * $e[$j]; + if ($wantu) { + for ($i = 0; $i < $this->m; ++$i) { + $t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$k-1]; + $this->U[$i][$k-1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$k-1]; + $this->U[$i][$j] = $t; + } + } + } + break; + // Perform one qr step. + case 3: + // Calculate the shift. + $scale = max(max(max(max( + abs($this->s[$p-1]),abs($this->s[$p-2])),abs($e[$p-2])), + abs($this->s[$k])), abs($e[$k])); + $sp = $this->s[$p-1] / $scale; + $spm1 = $this->s[$p-2] / $scale; + $epm1 = $e[$p-2] / $scale; + $sk = $this->s[$k] / $scale; + $ek = $e[$k] / $scale; + $b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0; + $c = ($sp * $epm1) * ($sp * $epm1); + $shift = 0.0; + if (($b != 0.0) || ($c != 0.0)) { + $shift = sqrt($b * $b + $c); + if ($b < 0.0) { + $shift = -$shift; + } + $shift = $c / ($b + $shift); + } + $f = ($sk + $sp) * ($sk - $sp) + $shift; + $g = $sk * $ek; + // Chase zeros. + for ($j = $k; $j < $p-1; ++$j) { + $t = hypo($f,$g); + $cs = $f/$t; + $sn = $g/$t; + if ($j != $k) { + $e[$j-1] = $t; + } + $f = $cs * $this->s[$j] + $sn * $e[$j]; + $e[$j] = $cs * $e[$j] - $sn * $this->s[$j]; + $g = $sn * $this->s[$j+1]; + $this->s[$j+1] = $cs * $this->s[$j+1]; + if ($wantv) { + for ($i = 0; $i < $this->n; ++$i) { + $t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$j+1]; + $this->V[$i][$j+1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$j+1]; + $this->V[$i][$j] = $t; + } + } + $t = hypo($f,$g); + $cs = $f/$t; + $sn = $g/$t; + $this->s[$j] = $t; + $f = $cs * $e[$j] + $sn * $this->s[$j+1]; + $this->s[$j+1] = -$sn * $e[$j] + $cs * $this->s[$j+1]; + $g = $sn * $e[$j+1]; + $e[$j+1] = $cs * $e[$j+1]; + if ($wantu && ($j < $this->m - 1)) { + for ($i = 0; $i < $this->m; ++$i) { + $t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$j+1]; + $this->U[$i][$j+1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$j+1]; + $this->U[$i][$j] = $t; + } + } + } + $e[$p-2] = $f; + $iter = $iter + 1; + break; + // Convergence. + case 4: + // Make the singular values positive. + if ($this->s[$k] <= 0.0) { + $this->s[$k] = ($this->s[$k] < 0.0 ? -$this->s[$k] : 0.0); + if ($wantv) { + for ($i = 0; $i <= $pp; ++$i) { + $this->V[$i][$k] = -$this->V[$i][$k]; + } + } + } + // Order the singular values. + while ($k < $pp) { + if ($this->s[$k] >= $this->s[$k+1]) { + break; + } + $t = $this->s[$k]; + $this->s[$k] = $this->s[$k+1]; + $this->s[$k+1] = $t; + if ($wantv AND ($k < $this->n - 1)) { + for ($i = 0; $i < $this->n; ++$i) { + $t = $this->V[$i][$k+1]; + $this->V[$i][$k+1] = $this->V[$i][$k]; + $this->V[$i][$k] = $t; + } + } + if ($wantu AND ($k < $this->m-1)) { + for ($i = 0; $i < $this->m; ++$i) { + $t = $this->U[$i][$k+1]; + $this->U[$i][$k+1] = $this->U[$i][$k]; + $this->U[$i][$k] = $t; + } + } + ++$k; + } + $iter = 0; + --$p; + break; + } // end switch + } // end while - /** - * Return the right singular vectors - * @access public - * @return V - */ - function getV() { - return new Matrix($this->V); - } + } // end constructor - /** - * Return the one-dimensional array of singular values - * @access public - * @return diagonal of S. - */ - function getSingularValues() { - return $this->s; - } - /** - * Return the diagonal matrix of singular values - * @access public - * @return S - */ - function getS() { - for ($i = 0; $i < $this->n; $i++) { - for ($j = 0; $j < $this->n; $j++) - $S[$i][$j] = 0.0; - $S[$i][$i] = $this->s[$i]; - } - return new Matrix($S); - } + /** + * Return the left singular vectors + * + * @access public + * @return U + */ + public function getU() { + return new Matrix($this->U, $this->m, min($this->m + 1, $this->n)); + } - /** - * Two norm - * @access public - * @return max(S) - */ - function norm2() { - return $this->s[0]; - } - /** - * Two norm condition number - * @access public - * @return max(S)/min(S) - */ - function cond() { - return $this->s[0] / $this->s[min($this->m, $this->n) - 1]; - } + /** + * Return the right singular vectors + * + * @access public + * @return V + */ + public function getV() { + return new Matrix($this->V); + } - /** - * Effective numerical matrix rank - * @access public - * @return Number of nonnegligible singular values. - */ - function rank() { - $eps = pow(2.0, -52.0); - $tol = max($this->m, $this->n) * $this->s[0] * $eps; - $r = 0; - for ($i = 0; $i < count($this->s); $i++) { - if ($this->s[$i] > $tol) - $r++; - } - return $r; - } -} + + /** + * Return the one-dimensional array of singular values + * + * @access public + * @return diagonal of S. + */ + public function getSingularValues() { + return $this->s; + } + + + /** + * Return the diagonal matrix of singular values + * + * @access public + * @return S + */ + public function getS() { + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + $S[$i][$j] = 0.0; + } + $S[$i][$i] = $this->s[$i]; + } + return new Matrix($S); + } + + + /** + * Two norm + * + * @access public + * @return max(S) + */ + public function norm2() { + return $this->s[0]; + } + + + /** + * Two norm condition number + * + * @access public + * @return max(S)/min(S) + */ + public function cond() { + return $this->s[0] / $this->s[min($this->m, $this->n) - 1]; + } + + + /** + * Effective numerical matrix rank + * + * @access public + * @return Number of nonnegligible singular values. + */ + public function rank() { + $eps = pow(2.0, -52.0); + $tol = max($this->m, $this->n) * $this->s[0] * $eps; + $r = 0; + for ($i = 0; $i < count($this->s); ++$i) { + if ($this->s[$i] > $tol) { + ++$r; + } + } + return $r; + } + +} // class SingularValueDecomposition diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Error.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Error.php index 29628a8e7..e73252b3d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Error.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Error.php @@ -1,120 +1,82 @@ Error: ' . $error[$lang][$num] . '
' . $file . ' @ L' . $line . ''; - die(); - break; - - case WARNING: - echo '
Warning: ' . $error[$lang][$num] . '
' . $file . ' @ L' . $line . '
'; - break; - - case NOTICE: - //echo '
Notice: ' . $error[$lang][$num] . '
' . $file . ' @ L' . $line . '
'; - break; + * Custom error handler + * @param int $num Error number + */ +function JAMAError($errorNumber = null) { + global $error; - case E_NOTICE: - //echo '
Notice: ' . $error[$lang][$num] . '
' . $file . ' @ L' . $line . '
'; - break; - - case E_STRICT: - break; - - case E_WARNING: - break; - - default: - echo "
Unknown Error Type: $type - $file @ L{$line}
"; - die(); - break; - } - } else { - die( "Invalid arguments to JAMAError()" ); - } + if (isset($errorNumber)) { + if (isset($error[JAMALANG][$errorNumber])) { + return $error[JAMALANG][$errorNumber]; + } else { + return $error['EN'][$errorNumber]; + } + } else { + return ("Invalid argument to JAMAError()"); + } } - -// TODO MarkBaker -//set_error_handler('JAMAError'); -//error_reporting(ERROR | WARNING); - diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Maths.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Maths.php index dfe7733cb..f5e2a3721 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Maths.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/utils/Maths.php @@ -1,40 +1,43 @@ abs($b)) { - $r = $b/$a; - $r = abs($a)* sqrt(1+$r*$r); - } else if ($b != 0) { - $r = $a/$b; - $r = abs($b)*sqrt(1+$r*$r); - } else - $r = 0.0; - return $r; -} + if (abs($a) > abs($b)) { + $r = $b / $a; + $r = abs($a) * sqrt(1 + $r * $r); + } elseif ($b != 0) { + $r = $a / $b; + $r = abs($b) * sqrt(1 + $r * $r); + } else { + $r = 0.0; + } + return $r; +} // function hypo() + /** -* Mike Bommarito's version. -* Compute n-dimensional hyotheneuse. -* + * Mike Bommarito's version. + * Compute n-dimensional hyotheneuse. + * function hypot() { - $s = 0; - foreach (func_get_args() as $d) { - if (is_numeric($d)) - $s += pow($d, 2); - else - trigger_error(ArgumentTypeException, ERROR); - } - return sqrt($s); + $s = 0; + foreach (func_get_args() as $d) { + if (is_numeric($d)) { + $s += pow($d, 2); + } else { + throw new Exception(JAMAError(ArgumentTypeException)); + } + } + return sqrt($s); } */ From 9e6e0dc11a0322523008046f6af890544d2463f5 Mon Sep 17 00:00:00 2001 From: Dieter Adriaenssens Date: Sun, 2 May 2010 21:01:53 +0200 Subject: [PATCH 2/6] upgrade to PHPExcel 1.7.2 --- libraries/PHPExcel/PHPExcel.php | 65 +- libraries/PHPExcel/PHPExcel/Calculation.php | 791 ++++-- .../PHPExcel/Calculation/Exception.php | 8 +- .../PHPExcel/Calculation/ExceptionHandler.php | 8 +- .../PHPExcel/Calculation/FormulaParser.php | 8 +- .../PHPExcel/Calculation/FormulaToken.php | 8 +- .../PHPExcel/Calculation/Function.php | 8 +- .../PHPExcel/Calculation/Functions.php | 2335 ++++++++++++----- libraries/PHPExcel/PHPExcel/Cell.php | 78 +- .../PHPExcel/Cell/AdvancedValueBinder.php | 24 +- libraries/PHPExcel/PHPExcel/Cell/DataType.php | 48 +- .../PHPExcel/PHPExcel/Cell/DataValidation.php | 8 +- .../PHPExcel/Cell/DefaultValueBinder.php | 19 +- .../PHPExcel/PHPExcel/Cell/Hyperlink.php | 8 +- .../PHPExcel/PHPExcel/Cell/IValueBinder.php | 8 +- libraries/PHPExcel/PHPExcel/Comment.php | 39 +- .../PHPExcel/PHPExcel/DocumentProperties.php | 8 +- .../PHPExcel/PHPExcel/DocumentSecurity.php | 8 +- libraries/PHPExcel/PHPExcel/HashTable.php | 32 +- libraries/PHPExcel/PHPExcel/IComparable.php | 27 +- libraries/PHPExcel/PHPExcel/IOFactory.php | 110 +- libraries/PHPExcel/PHPExcel/NamedRange.php | 8 +- libraries/PHPExcel/PHPExcel/Reader/CSV.php | 59 +- .../PHPExcel/Reader/DefaultReadFilter.php | 8 +- .../PHPExcel/PHPExcel/Reader/Excel2003XML.php | 698 +++++ .../PHPExcel/PHPExcel/Reader/Excel2007.php | 1773 +++++++------ libraries/PHPExcel/PHPExcel/Reader/Excel5.php | 817 +++++- .../PHPExcel/Reader/Excel5/Escher.php | 8 +- .../PHPExcel/PHPExcel/Reader/IReadFilter.php | 8 +- .../PHPExcel/PHPExcel/Reader/IReader.php | 8 +- libraries/PHPExcel/PHPExcel/Reader/OOCalc.php | 500 ++++ libraries/PHPExcel/PHPExcel/Reader/SYLK.php | 506 ++++ .../PHPExcel/PHPExcel/Reader/Serialized.php | 8 +- .../PHPExcel/PHPExcel/ReferenceHelper.php | 260 +- libraries/PHPExcel/PHPExcel/RichText.php | 41 +- .../PHPExcel/RichText/ITextElement.php | 6 +- libraries/PHPExcel/PHPExcel/RichText/Run.php | 6 +- .../PHPExcel/RichText/TextElement.php | 6 +- libraries/PHPExcel/PHPExcel/Shared/Date.php | 17 +- .../PHPExcel/PHPExcel/Shared/Drawing.php | 90 +- libraries/PHPExcel/PHPExcel/Shared/Escher.php | 8 +- .../PHPExcel/Shared/Escher/DgContainer.php | 8 +- .../Escher/DgContainer/SpgrContainer.php | 8 +- .../DgContainer/SpgrContainer/SpContainer.php | 8 +- .../PHPExcel/Shared/Escher/DggContainer.php | 8 +- .../Escher/DggContainer/BstoreContainer.php | 8 +- .../DggContainer/BstoreContainer/BSE.php | 8 +- .../DggContainer/BstoreContainer/BSE/Blip.php | 8 +- libraries/PHPExcel/PHPExcel/Shared/Excel5.php | 36 +- libraries/PHPExcel/PHPExcel/Shared/File.php | 48 +- libraries/PHPExcel/PHPExcel/Shared/Font.php | 665 ++++- .../PHPExcel/PHPExcel/Shared/JAMA/Matrix.php | 87 +- .../Shared/OLE/ChainedBlockStream.php | 4 +- .../PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php | 2 +- .../PHPExcel/PHPExcel/Shared/OLERead.php | 6 +- libraries/PHPExcel/PHPExcel/Shared/PDF.php | 6 +- .../PHPExcel/Shared/PasswordHasher.php | 8 +- libraries/PHPExcel/PHPExcel/Shared/String.php | 135 +- .../PHPExcel/PHPExcel/Shared/XMLWriter.php | 8 +- .../PHPExcel/Shared/ZipStreamWrapper.php | 10 +- .../PHPExcel/Shared/trend/bestFitClass.php | 26 +- .../Shared/trend/exponentialBestFitClass.php | 18 +- .../Shared/trend/linearBestFitClass.php | 8 +- .../Shared/trend/logarithmicBestFitClass.php | 18 +- .../Shared/trend/polynomialBestFitClass.php | 8 +- .../Shared/trend/powerBestFitClass.php | 28 +- libraries/PHPExcel/PHPExcel/Style.php | 488 ++-- .../PHPExcel/PHPExcel/Style/Alignment.php | 61 +- libraries/PHPExcel/PHPExcel/Style/Border.php | 53 +- libraries/PHPExcel/PHPExcel/Style/Borders.php | 52 +- libraries/PHPExcel/PHPExcel/Style/Color.php | 53 +- .../PHPExcel/PHPExcel/Style/Conditional.php | 39 +- libraries/PHPExcel/PHPExcel/Style/Fill.php | 57 +- libraries/PHPExcel/PHPExcel/Style/Font.php | 67 +- .../PHPExcel/PHPExcel/Style/NumberFormat.php | 260 +- .../PHPExcel/PHPExcel/Style/Protection.php | 51 +- libraries/PHPExcel/PHPExcel/Worksheet.php | 492 ++-- .../PHPExcel/Worksheet/BaseDrawing.php | 39 +- .../PHPExcel/Worksheet/CellIterator.php | 41 +- .../PHPExcel/Worksheet/ColumnDimension.php | 45 +- .../PHPExcel/PHPExcel/Worksheet/Drawing.php | 39 +- .../PHPExcel/Worksheet/Drawing/Shadow.php | 39 +- .../PHPExcel/Worksheet/HeaderFooter.php | 10 +- .../Worksheet/HeaderFooterDrawing.php | 39 +- .../PHPExcel/Worksheet/MemoryDrawing.php | 39 +- .../PHPExcel/Worksheet/PageMargins.php | 8 +- .../PHPExcel/PHPExcel/Worksheet/PageSetup.php | 104 +- .../PHPExcel/Worksheet/Protection.php | 8 +- libraries/PHPExcel/PHPExcel/Worksheet/Row.php | 8 +- .../PHPExcel/Worksheet/RowDimension.php | 44 +- .../PHPExcel/Worksheet/RowIterator.php | 8 +- .../PHPExcel/PHPExcel/Worksheet/SheetView.php | 8 +- .../PHPExcel/PHPExcel/WorksheetIterator.php | 8 +- libraries/PHPExcel/PHPExcel/Writer/CSV.php | 8 +- .../PHPExcel/PHPExcel/Writer/Excel2007.php | 8 +- .../PHPExcel/Writer/Excel2007/Comments.php | 14 +- .../Writer/Excel2007/ContentTypes.php | 8 +- .../PHPExcel/Writer/Excel2007/DocProps.php | 8 +- .../PHPExcel/Writer/Excel2007/Drawing.php | 16 +- .../PHPExcel/Writer/Excel2007/Rels.php | 18 +- .../PHPExcel/Writer/Excel2007/StringTable.php | 18 +- .../PHPExcel/Writer/Excel2007/Style.php | 12 +- .../PHPExcel/Writer/Excel2007/Theme.php | 8 +- .../PHPExcel/Writer/Excel2007/Workbook.php | 29 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 201 +- .../PHPExcel/Writer/Excel2007/WriterPart.php | 8 +- libraries/PHPExcel/PHPExcel/Writer/Excel5.php | 54 +- .../PHPExcel/Writer/Excel5/BIFFwriter.php | 8 +- .../PHPExcel/Writer/Excel5/Escher.php | 12 +- .../PHPExcel/PHPExcel/Writer/Excel5/Font.php | 8 +- .../PHPExcel/Writer/Excel5/Parser.php | 102 +- .../PHPExcel/Writer/Excel5/Workbook.php | 134 +- .../PHPExcel/Writer/Excel5/Worksheet.php | 387 ++- .../PHPExcel/PHPExcel/Writer/Excel5/Xf.php | 31 +- libraries/PHPExcel/PHPExcel/Writer/HTML.php | 238 +- .../PHPExcel/PHPExcel/Writer/IWriter.php | 8 +- libraries/PHPExcel/PHPExcel/Writer/PDF.php | 19 +- .../PHPExcel/PHPExcel/Writer/Serialized.php | 12 +- 118 files changed, 9154 insertions(+), 4035 deletions(-) create mode 100644 libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php create mode 100644 libraries/PHPExcel/PHPExcel/Reader/OOCalc.php create mode 100644 libraries/PHPExcel/PHPExcel/Reader/SYLK.php diff --git a/libraries/PHPExcel/PHPExcel.php b/libraries/PHPExcel/PHPExcel.php index ac5f00246..a7ff765de 100644 --- a/libraries/PHPExcel/PHPExcel.php +++ b/libraries/PHPExcel/PHPExcel.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/WorksheetIterator.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel { @@ -212,6 +212,8 @@ class PHPExcel * Add sheet * * @param PHPExcel_Worksheet $pSheet + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @return PHPExcel_Worksheet * @throws Exception */ public function addSheet(PHPExcel_Worksheet $pSheet = null, $iSheetIndex = null) @@ -229,7 +231,14 @@ class PHPExcel 0, array($pSheet) ); + + // Adjust active sheet index if necessary + if ($this->_activeSheetIndex >= $iSheetIndex) { + ++$this->_activeSheetIndex; + } + } + return $pSheet; } /** @@ -390,10 +399,11 @@ class PHPExcel * Add external sheet * * @param PHPExcel_Worksheet $pSheet External sheet to add + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) * @throws Exception * @return PHPExcel_Worksheet */ - public function addExternalSheet(PHPExcel_Worksheet $pSheet) { + public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) { if (!is_null($this->getSheetByName($pSheet->getTitle()))) { throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first."); } @@ -414,7 +424,7 @@ class PHPExcel $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); } - return $this->addSheet($pSheet); + return $this->addSheet($pSheet, $iSheetIndex); } /** @@ -700,7 +710,8 @@ class PHPExcel } /** - * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells in the workbook + * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells + * and columns in the workbook */ public function garbageCollect() { @@ -711,12 +722,27 @@ class PHPExcel } foreach ($this->getWorksheetIterator() as $sheet) { + + // from cells foreach ($sheet->getCellCollection(false) as $cell) { ++$countReferencesCellXf[$cell->getXfIndex()]; } + + // from row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + ++$countReferencesCellXf[$rowDimension->getXfIndex()]; + } + } + + // from column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + ++$countReferencesCellXf[$columnDimension->getXfIndex()]; + } } - // remove those cellXfs that have zero references and create mapping so we can update xfIndex for all cells + // remove cellXfs without references and create mapping so we can update xfIndex + // for all cells and columns $countNeededCellXfs = 0; foreach ($this->_cellXfCollection as $index => $cellXf) { if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf @@ -728,16 +754,35 @@ class PHPExcel } $this->_cellXfCollection = array_values($this->_cellXfCollection); - // if we removed the first style by accident, recreate it + // update the index for all cellXfs + foreach ($this->_cellXfCollection as $i => $cellXf) { + echo $cellXf->setIndex($i); + } + + // make sure there is always at least one cellXf (there should be) if (count($this->_cellXfCollection) == 0) { $this->_cellXfCollection[] = new PHPExcel_Style(); } - // update the xfIndex for all cells + // update the xfIndex for all cells, row dimensions, column dimensions foreach ($this->getWorksheetIterator() as $sheet) { + + // for all cells foreach ($sheet->getCellCollection(false) as $cell) { $cell->setXfIndex( $map[$cell->getXfIndex()] ); } + + // for all row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] ); + } + } + + // for all column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); + } } // also do garbage collection for all the sheets diff --git a/libraries/PHPExcel/PHPExcel/Calculation.php b/libraries/PHPExcel/PHPExcel/Calculation.php index 5ade6558c..793734f91 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation.php +++ b/libraries/PHPExcel/PHPExcel/Calculation.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation { @@ -62,20 +62,21 @@ class PHPExcel_Calculation { // Opening bracket const CALCULATION_REGEXP_OPENBRACE = '\('; // Function - const CALCULATION_REGEXP_FUNCTION = '([A-Z][A-Z0-9\.]*)[\s]*\('; + const CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\('; // Cell reference (cell or range of cells, with or without a sheet reference) - const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'.*\')|(\".*\"))!)?\$?([a-z]+)\$?(\d+)(:\$?([a-z]+)\$?(\d+))?'; + const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]+)\$?(\d+)'; // Named Range of cells const CALCULATION_REGEXP_NAMEDRANGE = '(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9]*)'; // Error - const CALCULATION_REGEXP_ERROR = '\#[^!]+!'; + const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?'; /** constants */ + const RETURN_ARRAY_AS_ERROR = 'error'; const RETURN_ARRAY_AS_VALUE = 'value'; const RETURN_ARRAY_AS_ARRAY = 'array'; - private static $returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; + private static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE; /** * Instance of this class @@ -110,7 +111,7 @@ class PHPExcel_Calculation { * @access private * @var float */ - private $_calculationCacheExpirationTime = 0.01; + private $_calculationCacheExpirationTime = 2.5; /** @@ -119,7 +120,7 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_operators = array('+', '-', '*', '/', '^', '&', '%', '_', '>', '<', '=', '>=', '<=', '<>'); + private $_operators = array('+', '-', '*', '/', '^', '&', '%', '~', '>', '<', '=', '>=', '<=', '<>', '|', ':'); /** @@ -128,7 +129,7 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>'); + private $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>', '|', ':'); public $suppressFormulaErrors = false; public $formulaError = null; @@ -170,11 +171,11 @@ class PHPExcel_Calculation { 'argumentCount' => '2-5' ), 'AMORDEGRC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::AMORDEGRC', 'argumentCount' => '6,7' ), 'AMORLINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::AMORLINC', 'argumentCount' => '6,7' ), 'AND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, @@ -311,10 +312,11 @@ class PHPExcel_Calculation { ), 'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_Functions::COLUMN', - 'argumentCount' => '-1' + 'argumentCount' => '-1', + 'passByReference' => array(true) ), 'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COLUMNS', 'argumentCount' => '1' ), 'COMBIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -386,7 +388,7 @@ class PHPExcel_Calculation { 'argumentCount' => '3,4' ), 'COUPNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPNUM', 'argumentCount' => '3,4' ), 'COUPPCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -443,7 +445,7 @@ class PHPExcel_Calculation { ), 'DATEDIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::DATEDIF', - 'argumentCount' => '3' + 'argumentCount' => '2,3' ), 'DATEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::DATEVALUE', @@ -658,7 +660,7 @@ class PHPExcel_Calculation { 'argumentCount' => '3-5' ), 'FVSCHEDULE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::FVSCHEDULE', 'argumentCount' => '2' ), 'GAMMADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -731,7 +733,7 @@ class PHPExcel_Calculation { ), 'IFERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, 'functionCall' => 'PHPExcel_Calculation_Functions::STATEMENT_IFERROR', - 'argumentCount' => '1' + 'argumentCount' => '2' ), 'IMABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, 'functionCall' => 'PHPExcel_Calculation_Functions::IMABS', @@ -806,8 +808,9 @@ class PHPExcel_Calculation { 'argumentCount' => '1-4' ), 'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '1,2' + 'functionCall' => 'PHPExcel_Calculation_Functions::INDIRECT', + 'argumentCount' => '1,2', + 'passCellReference'=> true ), 'INFO' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', @@ -830,7 +833,7 @@ class PHPExcel_Calculation { 'argumentCount' => '4-6' ), 'IRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::IRR', 'argumentCount' => '1,2' ), 'ISBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -870,7 +873,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'ISPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::ISPMT', 'argumentCount' => '4' ), 'ISREF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -961,6 +964,10 @@ class PHPExcel_Calculation { 'functionCall' => 'PHPExcel_Calculation_Functions::MAXA', 'argumentCount' => '1+' ), + 'MAXIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), 'MDETERM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, 'functionCall' => 'PHPExcel_Calculation_Functions::MDETERM', 'argumentCount' => '1' @@ -973,6 +980,10 @@ class PHPExcel_Calculation { 'functionCall' => 'PHPExcel_Calculation_Functions::MEDIAN', 'argumentCount' => '1+' ), + 'MEDIANIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), 'MID' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, 'functionCall' => 'PHPExcel_Calculation_Functions::MID', 'argumentCount' => '3' @@ -989,6 +1000,10 @@ class PHPExcel_Calculation { 'functionCall' => 'PHPExcel_Calculation_Functions::MINA', 'argumentCount' => '1+' ), + 'MINIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), 'MINUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::MINUTEOFHOUR', 'argumentCount' => '1' @@ -998,7 +1013,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'MIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::MIRR', 'argumentCount' => '3' ), 'MMULT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1111,7 +1126,9 @@ class PHPExcel_Calculation { ), 'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_Functions::OFFSET', - 'argumentCount' => '3,5' + 'argumentCount' => '3,5', + 'passCellReference'=> true, + 'passByReference' => array(true) ), 'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_OR', @@ -1210,7 +1227,7 @@ class PHPExcel_Calculation { 'argumentCount' => '2,3' ), 'RATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::RATE', 'argumentCount' => '3-6' ), 'RECEIVED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1255,10 +1272,11 @@ class PHPExcel_Calculation { ), 'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_Functions::ROW', - 'argumentCount' => '-1' + 'argumentCount' => '-1', + 'passByReference' => array(true) ), 'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::ROWS', 'argumentCount' => '1' ), 'RSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -1346,7 +1364,7 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'SUBSTITUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::SUBSTITUTE', 'argumentCount' => '3,4' ), 'SUBTOTAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1366,7 +1384,7 @@ class PHPExcel_Calculation { 'argumentCount' => '?' ), 'SUMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::SUMPRODUCT', 'argumentCount' => '1+' ), 'SUMSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1526,11 +1544,11 @@ class PHPExcel_Calculation { 'argumentCount' => '2+' ), 'XIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::XIRR', 'argumentCount' => '2,3' ), 'XNPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::XNPV', 'argumentCount' => '3' ), 'YEAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, @@ -1554,8 +1572,8 @@ class PHPExcel_Calculation { 'argumentCount' => '5,6' ), 'ZTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'functionCall' => 'PHPExcel_Calculation_Functions::ZTEST', + 'argumentCount' => '2-3' ) ); @@ -1563,7 +1581,7 @@ class PHPExcel_Calculation { // Internal functions used for special control purposes private $_controlFunctions = array( 'MKMATRIX' => array('argumentCount' => '*', - 'functionCall' => array('self','_mkMatrix') + 'functionCall' => 'self::_mkMatrix' ) ); @@ -1592,7 +1610,7 @@ class PHPExcel_Calculation { * @throws Exception */ public final function __clone() { - throw new Exception ( 'Cloning a Singleton is not allowed!' ); + throw new Exception ('Cloning a Singleton is not allowed!'); } // function __clone() @@ -1605,6 +1623,7 @@ class PHPExcel_Calculation { */ public static function setArrayReturnType($returnType) { if (($returnType == self::RETURN_ARRAY_AS_VALUE) || + ($returnType == self::RETURN_ARRAY_AS_ERROR) || ($returnType == self::RETURN_ARRAY_AS_ARRAY)) { self::$returnArrayAsType = $returnType; return True; @@ -1686,7 +1705,7 @@ class PHPExcel_Calculation { * * @param float $pValue */ - public function setCalculationCacheExpirationTime($pValue = 0.01) { + public function setCalculationCacheExpirationTime($pValue = 2.5) { $this->_calculationCacheExpirationTime = $pValue; } // function setCalculationCacheExpirationTime() @@ -1765,19 +1784,49 @@ class PHPExcel_Calculation { if ($resetLog) { // Initialise the logging settings if requested $this->formulaError = null; - $this->debugLog = array(); - $this->debugLogStack = array(); + $this->debugLog = $this->debugLogStack = array(); + + $returnArrayAsType = self::$returnArrayAsType; + self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; } // Read the formula from the cell if (is_null($pCell)) { return null; } - $formula = $pCell->getValue(); - $cellID = $pCell->getCoordinate(); + if ($resetLog) { + self::$returnArrayAsType = $returnArrayAsType; + } // Execute the calculation for the cell formula - return self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); + $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); + + if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { + $testResult = PHPExcel_Calculation_Functions::flattenArray($result); + if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) { + return PHPExcel_Calculation_Functions::VALUE(); + } + // If there's only a single cell in the array, then we allow it + if (count($testResult) != 1) { + // If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it + $r = array_shift(array_keys($result)); + if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); } + if (is_array($result[$r])) { + $c = array_shift(array_keys($result[$r])); + if (!is_numeric($c)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + } + $result = array_shift($testResult); + } + + if (is_null($result)) { + return 0; + } elseif((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) { + return PHPExcel_Calculation_Functions::NaN(); + } + return $result; } // function calculateCellValue( @@ -1812,8 +1861,7 @@ class PHPExcel_Calculation { public function calculateFormula($formula, $cellID=null, PHPExcel_Cell $pCell = null) { // Initialise the logging settings $this->formulaError = null; - $this->debugLog = array(); - $this->debugLogStack = array(); + $this->debugLog = $this->debugLogStack = array(); // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache @@ -1849,30 +1897,34 @@ class PHPExcel_Calculation { $formulaLength = strlen($formula); if ($formulaLength < 1) return self::_wrapResult($formula); + $wsTitle = 'Wrk'; + if (!is_null($pCell)) { + $wsTitle = urlencode($pCell->getParent()->getTitle()); + } // Is calculation cacheing enabled? if (!is_null($cellID)) { if ($this->_calculationCacheEnabled) { // Is the value present in calculation cache? // echo 'Testing cache value
'; - if (isset($this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()])) { + if (isset($this->_calculationCache[$wsTitle][$cellID])) { // echo 'Value is in cache
'; - $this->_writeDebug($cellID,'Testing cache value'); + $this->_writeDebug('Testing cache value for cell '.$cellID); // Is cache still valid? - if ((time() + microtime()) - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['time'] < $this->_calculationCacheExpirationTime) { + if ((time() + microtime(true)) - $this->_calculationCache[$wsTitle][$cellID]['time'] < $this->_calculationCacheExpirationTime) { // echo 'Cache time is still valid
'; - $this->_writeDebug($cellID,'Retrieving value from cache'); + $this->_writeDebug('Retrieving value for '.$cellID.' from cache'); // Return the cached result - $returnValue = $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['data']; -// echo 'Retrieving data value of '.$returnValue.' for '.$pCell->getCoordinate().' from cache
'; + $returnValue = $this->_calculationCache[$wsTitle][$cellID]['data']; +// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
'; if (is_array($returnValue)) { return array_shift(PHPExcel_Calculation_Functions::flattenArray($returnValue)); } return $returnValue; } else { // echo 'Cache has expired
'; - $this->_writeDebug($cellID,'Cache value has expired'); + $this->_writeDebug('Cache value for '.$cellID.' has expired'); // Clear the cache if it's no longer valid - unset($this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]); + unset($this->_calculationCache[$wsTitle][$cellID]); } } } @@ -1886,16 +1938,12 @@ class PHPExcel_Calculation { // Save to calculation cache if (!is_null($cellID)) { if ($this->_calculationCacheEnabled) { - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['time'] = (time() + microtime()); - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['data'] = $cellValue; + $this->_calculationCache[$wsTitle][$cellID]['time'] = (time() + microtime(true)); + $this->_calculationCache[$wsTitle][$cellID]['data'] = $cellValue; } } // Return the calculated value - if (is_array($cellValue)) { - $cellValue = array_shift(PHPExcel_Calculation_Functions::flattenArray($cellValue)); - } - return $cellValue; } // function _calculateFormulaValue() @@ -1903,8 +1951,14 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices and of the same size * - * @param mixed $operand1 First matrix operand - * @param mixed $operand2 Second matrix operand + * @param mixed &$operand1 First matrix operand + * @param mixed &$operand2 Second matrix operand + * @param integer $resize Flag indicating whether the matrices should be resized to match + * and (if so), whether the smaller dimension should grow or the + * larger should shrink. + * 0 = no resize + * 1 = shrink to fit + * 2 = extend to fit */ private static function _checkMatrixOperands(&$operand1,&$operand2,$resize = 1) { // Examine each of the two operands, and turn them into an array if they aren't one already @@ -1919,36 +1973,29 @@ class PHPExcel_Calculation { $resize = 0; } - // Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger + list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($operand1); + list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($operand2); + if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) { + $resize = 1; + } + if ($resize == 2) { + // Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger self::_resizeMatricesExtend($operand1,$operand2); } elseif ($resize == 1) { + // Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller self::_resizeMatricesShrink($operand1,$operand2); } } // function _checkMatrixOperands() - /** - * Re-index a matrix with straight numeric keys starting from row 0, column 0 - * - * @param mixed $matrix matrix operand - * @return array The re-indexed matrix - */ - private static function _reindexMatrixDimensions($matrix) { - foreach($matrix as $rowKey => $rowValue) { - $matrix[$rowKey] = array_values($rowValue); - } - return array_values($matrix); - } // function _getMatrixDimensions() - - /** * Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0 * - * @param mixed $matrix matrix operand + * @param mixed &$matrix matrix operand * @return array An array comprising the number of rows, and number of columns */ - private static function _getMatrixDimensions(&$matrix) { + public static function _getMatrixDimensions(&$matrix) { $matrixRows = count($matrix); $matrixColumns = 0; foreach($matrix as $rowKey => $rowValue) { @@ -1966,8 +2013,8 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices of the same size * - * @param mixed $matrix1 First matrix operand - * @param mixed $matrix2 Second matrix operand + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand */ private static function _resizeMatricesShrink(&$matrix1,&$matrix2) { list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($matrix1); @@ -2008,8 +2055,8 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices of the same size * - * @param mixed $matrix1 First matrix operand - * @param mixed $matrix2 Second matrix operand + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand */ private static function _resizeMatricesExtend(&$matrix1,&$matrix2) { list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($matrix1); @@ -2059,24 +2106,17 @@ class PHPExcel_Calculation { */ private static function _showValue($value) { if (is_array($value)) { - $retVal = ''; - $i = 0; + $returnMatrix = array(); + $pad = $rpad = ', '; foreach($value as $row) { if (is_array($row)) { - if ($i > 0) { $retVal .= '; '; } - $j = 0; - foreach($row as $column) { - if ($j > 0) { $retVal .= ', '; } - $retVal .= $column; - ++$j; - } + $returnMatrix[] = implode($pad,$row); + $rpad = '; '; } else { - if ($i > 0) { $retVal .= ', '; } - $retVal .= $row; + $returnMatrix[] = $row; } - ++$i; } - return '{ '.$retVal.' }'; + return '{ '.implode($rpad,$returnMatrix).' }'; } elseif(is_bool($value)) { return ($value) ? 'TRUE' : 'FALSE'; } @@ -2128,17 +2168,16 @@ class PHPExcel_Calculation { // Convert any Excel matrix references to the MKMATRIX() function if (strpos($formula,'{') !== false) { - // Open and Closed counts used for trapping mismatched braces in the formula - $openCount = $closeCount = 0; // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators if (strpos($formula,'"') !== false) { // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded // the formula $temp = explode('"',$formula); - $i = 0; - foreach($temp as &$value) { + // Open and Closed counts used for trapping mismatched braces in the formula + $openCount = $closeCount = 0; + foreach($temp as $i => &$value) { // Only count/replace in alternate array entries - if (($i++ % 2) == 0) { + if (($i % 2) == 0) { $openCount += substr_count($value,'{'); $closeCount += substr_count($value,'}'); $value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value); @@ -2149,8 +2188,8 @@ class PHPExcel_Calculation { $formula = implode('"',$temp); } else { // If there's no quoted strings, then we do a simple count/replace - $openCount += substr_count($formula,'{'); - $closeCount += substr_count($formula,'}'); + $openCount = substr_count($formula,'{'); + $closeCount = substr_count($formula,'}'); $formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula); } // Trap for mismatched braces and trigger an appropriate error @@ -2190,7 +2229,8 @@ class PHPExcel_Calculation { $operatorAssociativity = array('^' => 0, // Exponentiation '*' => 0, '/' => 0, // Multiplication and Division '+' => 0, '-' => 0, // Addition and Subtraction - '&' => 1, // Concatenation + '&' => 0, // Concatenation + '|' => 0, ':' => 0, // Intersect and Range '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison ); // Comparison (Boolean) Operators @@ -2200,7 +2240,9 @@ class PHPExcel_Calculation { // Operator Precedence // This list includes all valid operators, whether binary (including boolean) or unary (such as %) // Array key is the operator, the value is its precedence - $operatorPrecedence = array('_' => 6, // Negation + $operatorPrecedence = array(':' => 8, // Range + '|' => 7, // Intersect + '~' => 6, // Negation '%' => 5, // Percentage '^' => 4, // Exponentiation '*' => 3, '/' => 3, // Multiplication and Division @@ -2215,7 +2257,8 @@ class PHPExcel_Calculation { '|'.self::CALCULATION_REGEXP_OPENBRACE. '|'.self::CALCULATION_REGEXP_CELLREF. '|'.self::CALCULATION_REGEXP_NAMEDRANGE. - ')/i'; + '|'.self::CALCULATION_REGEXP_ERROR. + ')/si'; // Start with initialisation $index = 0; @@ -2242,44 +2285,43 @@ class PHPExcel_Calculation { if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? // echo 'Element is a Negation operator
'; - $stack->push('_'); // Put a negation on the stack + $stack->push('Unary Operator','~'); // Put a negation on the stack ++$index; // and drop the negation symbol } elseif ($opCharacter == '%' && $expectingOperator) { // echo 'Element is a Percentage operator
'; - $stack->push('%'); // Put a percentage on the stack + $stack->push('Unary Operator','%'); // Put a percentage on the stack ++$index; } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (rather than plus) can be discarded? // echo 'Element is a Positive number, not Plus operator
'; ++$index; // Drop the redundant plus symbol - } elseif (($opCharacter == '_') && (!$isOperandOrFunction)) { // We have to explicitly deny an underscore, because it's legal on - return $this->_raiseFormulaError("Formula Error: Illegal character '_'"); // the stack but not in the input expression - // Note that _ is a valid first character in named ranges - // and this will need modifying soon when we start integrating - // with PHPExcel proper + } elseif (($opCharacter == '~') && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, because it's legal + return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression } elseif ((in_array($opCharacter, $this->_operators) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? // echo 'Element with value '.$opCharacter.' is an Operator
'; while($stack->count() > 0 && ($o2 = $stack->last()) && - in_array($o2, $this->_operators) && - ($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2])) { + in_array($o2['value'], $this->_operators) && + @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } - $stack->push($opCharacter); // Finally put our current operator onto the stack + $stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack ++$index; $expectingOperator = false; } elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis? // echo 'Element is a Closing bracket
'; $expectingOperand = false; - while (($o2 = $stack->pop()) != '(') { // Pop off the stack back to the last ( + while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if (is_null($o2)) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"'); else $output[] = $o2; } - if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $stack->last(2), $matches)) { // Did this parenthesis just close a function? + $d = $stack->last(2); + if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) { // Did this parenthesis just close a function? $functionName = $matches[1]; // Get the function name // echo 'Closed Function is '.$functionName.'
'; - $argumentCount = $stack->pop(); // See how many arguments there were (argument count is the next value stored on the stack) + $d = $stack->pop(); + $argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack) // if ($argumentCount == 0) { // echo 'With no arguments
'; // } elseif ($argumentCount == 1) { @@ -2287,7 +2329,7 @@ class PHPExcel_Calculation { // } else { // echo 'With '.$argumentCount.' arguments
'; // } - $output[] = $argumentCount; // Dump the argument count on the output + $output[] = $d; // Dump the argument count on the output $output[] = $stack->pop(); // Pop the function and push onto the output if (array_key_exists($functionName, $this->_controlFunctions)) { // echo 'Built-in function '.$functionName.'
'; @@ -2349,27 +2391,29 @@ class PHPExcel_Calculation { } elseif ($opCharacter == ',') { // Is this the comma separator for function arguments? // echo 'Element is a Function argument separator
'; - while (($o2 = $stack->pop()) != '(') { + while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if (is_null($o2)) return $this->_raiseFormulaError("Formula Error: Unexpected ','"); else $output[] = $o2; // pop the argument expression stuff and push onto the output } // If we've a comma when we're expecting an operand, then what we actually have is a null operand; // so push a null onto the stack if (($expectingOperand) || (!$expectingOperator)) { - $output[] = $this->_ExcelConstants['NULL']; + $output[] = array('type' => 'NULL Value', 'value' => $this->_ExcelConstants['NULL'], 'reference' => NULL); } // make sure there was a function - if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $stack->last(2), $matches)) + $d = $stack->last(2); + if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) return $this->_raiseFormulaError("Formula Error: Unexpected ','"); - $stack->push($stack->pop()+1); // increment the argument count - $stack->push('('); // put the ( back on, we'll need to pop back to it again + $d = $stack->pop(); + $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count + $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again $expectingOperator = false; $expectingOperand = true; ++$index; } elseif ($opCharacter == '(' && !$expectingOperator) { // echo 'Element is an Opening Bracket
'; - $stack->push('('); + $stack->push('Brace', '('); ++$index; } elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number? @@ -2382,28 +2426,27 @@ class PHPExcel_Calculation { if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) { $val = preg_replace('/\s/','',$val); // echo 'Element '.$val.' is a Function
'; - if (array_key_exists(strtoupper($matches[1]), $this->_controlFunctions) || array_key_exists(strtoupper($matches[1]), $this->_PHPExcelFunctions)) { // it's a func - $stack->push(strtoupper($val)); + if (array_key_exists(strtoupper($matches[1]), $this->_PHPExcelFunctions) || array_key_exists(strtoupper($matches[1]), $this->_controlFunctions)) { // it's a func + $stack->push('Function', strtoupper($val)); $ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch); if ($ax) { - $stack->push(0); + $stack->push('Operand Count for Function '.strtoupper($val).')', 0); $expectingOperator = true; } else { - $stack->push(1); + $stack->push('Operand Count for Function '.strtoupper($val).')', 1); $expectingOperator = false; } - $stack->push('('); + $stack->push('Brace', '('); } else { // it's a var w/ implicit multiplication - $val = $matches[1]; - $output[] = $val; + $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => NULL); } } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) { // echo 'Element '.$val.' is a Cell reference
'; // Watch for this case-change when modifying to allow cell references in different worksheets... // Should only be applied to the actual cell column, not the worksheet name -// $cellRef = strtoupper($val); + $cellRef = strtoupper($val); // $output[] = $cellRef; - $output[] = $val; + $output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $cellRef); // $expectingOperator = false; } else { // it's a variable, constant, string, number or boolean // echo 'Element is a Variable, Constant, String, Number or Boolean
'; @@ -2412,25 +2455,25 @@ class PHPExcel_Calculation { $val = str_replace('""','"',$val); } elseif (is_numeric($val)) { // echo 'Element is a Number
'; - if ((strpos($val,'.') !== False) || (stripos($val,'e') !== False)) { + if ((strpos($val,'.') !== False) || (stripos($val,'e') !== False) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) { // echo 'Casting '.$val.' to float
'; $val = (float) $val; } else { // echo 'Casting '.$val.' to integer
'; $val = (integer) $val; } -// } elseif (array_key_exists(trim(strtoupper($val)), $this->_ExcelConstants)) { -// $excelConstant = trim(strtoupper($val)); -// echo 'Element '.$val.' is an Excel Constant
'; -// $val = $this->_ExcelConstants[$excelConstant]; + } elseif (array_key_exists(trim(strtoupper($val)), $this->_ExcelConstants)) { + $excelConstant = trim(strtoupper($val)); +// echo 'Element '.$excelConstant.' is an Excel Constant
'; + $val = $this->_ExcelConstants[$excelConstant]; } - $output[] = $val; + $output[] = array('type' => 'Value', 'value' => $val, 'reference' => NULL); } $index += $length; } elseif ($opCharacter == ')') { // miscellaneous error checking if ($expectingOperand) { - $output[] = $this->_ExcelConstants['NULL']; + $output[] = array('type' => 'Null Value', 'value' => $this->_ExcelConstants['NULL'], 'reference' => NULL); $expectingOperand = false; $expectingOperator = True; } else { @@ -2452,14 +2495,34 @@ class PHPExcel_Calculation { } } // Ignore white space - while (substr($formula, $index, 1) == ' ') { + while (($formula{$index} == "\n") || ($formula{$index} == "\r")) { ++$index; } + if ($formula{$index} == ' ') { + while ($formula{$index} == ' ') { + ++$index; + } + // If we're expecting an operator, but only have a space between the previous and next operands (and both are + // Cell References) then we have an INTERSECTION operator +// echo 'Possible Intersect Operator
'; + if (($expectingOperator) && (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'.*/i', substr($formula, $index), $match)) && + ($output[count($output)-1]['type'] == 'Cell Reference')) { +// echo 'Element is an Intersect Operator
'; + while($stack->count() > 0 && + ($o2 = $stack->last()) && + in_array($o2['value'], $this->_operators) && + @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { + $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output + } + $stack->push('Binary Operator','|'); // Put an Intersect Operator on the stack + $expectingOperator = false; + } + } } - while (!is_null($opCharacter = $stack->pop())) { // pop everything off the stack and push onto output - if ($opCharacter == '(') return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced - $output[] = $opCharacter; + while (!is_null($op = $stack->pop())) { // pop everything off the stack and push onto output + if ($opCharacter['value'] == '(') return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced + $output[] = $op; } return $output; } // function _parseFormula() @@ -2472,16 +2535,25 @@ class PHPExcel_Calculation { $stack = new PHPExcel_Token_Stack; // Loop through each token in turn - foreach ($tokens as $token) { + foreach ($tokens as $tokenData) { +// print_r($tokenData); +// echo '
'; + $token = $tokenData['value']; // echo 'Token is '.$token.'
'; // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack if (in_array($token, $this->_binaryOperators, true)) { // echo 'Token is a binary operator
'; // We must have two operands, error if we don't - if (is_null($operand2 = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); - if (is_null($operand1 = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + if (is_null($operand2Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + if (is_null($operand1Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); // Log what we're doing - $this->_writeDebug($cellID,'Evaluating '.self::_showValue($operand1).' '.$token.' '.self::_showValue($operand2)); + $operand1 = $operand1Data['value']; + $operand2 = $operand2Data['value']; + if ($token == ':') { + $this->_writeDebug('Evaluating Range '.self::_showValue($operand1Data['reference']).$token.self::_showValue($operand2Data['reference'])); + } else { + $this->_writeDebug('Evaluating '.self::_showValue($operand1).' '.$token.' '.self::_showValue($operand2)); + } // Process the operation in the appropriate manner switch ($token) { // Comparison (Boolean) Operators @@ -2494,6 +2566,53 @@ class PHPExcel_Calculation { $this->_executeBinaryComparisonOperation($cellID,$operand1,$operand2,$token,$stack); break; // Binary Operators + case ':' : // Range + $sheet1 = $sheet2 = ''; + if (strpos($operand1Data['reference'],'!') !== false) { + list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']); + } else { + $sheet1 = $pCell->getParent()->getTitle(); + } + if (strpos($operand2Data['reference'],'!') !== false) { + list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); + } else { + $sheet2 = $sheet1; + } + if ($sheet1 == $sheet2) { + if (is_null($operand1Data['reference'])) { + if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) { + $operand1Data['reference'] = $pCell->getColumn().$operand1Data['value']; + } elseif (trim($operand1Data['reference']) == '') { + $operand1Data['reference'] = $pCell->getColumn().$pCell->getRow(); + } else { + $operand1Data['reference'] = $operand1Data['value'].$pCell->getRow(); + } + } + if (is_null($operand2Data['reference'])) { + if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) { + $operand2Data['reference'] = $pCell->getColumn().$operand2Data['value']; + } elseif (trim($operand2Data['reference']) == '') { + $operand2Data['reference'] = $pCell->getColumn().$pCell->getRow(); + } else { + $operand2Data['reference'] = $operand2Data['value'].$pCell->getRow(); + } + } + + $oData = array_merge(explode(':',$operand1Data['reference']),explode(':',$operand2Data['reference'])); + $oCol = $oRow = array(); + foreach($oData as $oDatum) { + $oCR = PHPExcel_Cell::coordinateFromString($oDatum); + $oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1; + $oRow[] = $oCR[1]; + } + $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); + $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($sheet1), false); + $stack->push('Cell Reference',$cellValue,$cellRef); + } else { + $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL); + } + + break; case '+' : // Addition $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack); break; @@ -2513,9 +2632,15 @@ class PHPExcel_Calculation { // If either of the operands is a matrix, we need to treat them both as matrices // (converting the other operand to a matrix if need be); then perform the required // matrix operation + if (is_bool($operand1)) { + $operand1 = ($operand1) ? 'TRUE' : 'FALSE'; + } + if (is_bool($operand2)) { + $operand2 = ($operand2) ? 'TRUE' : 'FALSE'; + } if ((is_array($operand1)) || (is_array($operand2))) { // Ensure that both operands are arrays/matrices - self::_checkMatrixOperands($operand1,$operand2); + self::_checkMatrixOperands($operand1,$operand2,2); try { // Convert operand 1 from a PHP array to a matrix $matrix = new Matrix($operand1); @@ -2523,48 +2648,63 @@ class PHPExcel_Calculation { $matrixResult = $matrix->concat($operand2); $result = $matrixResult->getArray(); } catch (Exception $ex) { - $this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage()); + $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); $result = '#VALUE!'; } } else { $result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"'; } - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); - $stack->push($result); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + $stack->push('Value',$result); + break; + case '|' : // Intersect + $rowIntersect = array_intersect_key($operand1,$operand2); + $cellIntersect = $oCol = $oRow = array(); + foreach(array_keys($rowIntersect) as $col) { + $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1; + $cellIntersect[$col] = array_intersect_key($operand1[$col],$operand2[$col]); + foreach($cellIntersect[$col] as $row => $data) { + $oRow[] = $row; + } + } + $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($cellIntersect)); + $stack->push('Value',$cellIntersect,$cellRef); break; } // if the token is a unary operator, pop one value off the stack, do the operation, and push it back on - } elseif (($token === "_") || ($token === "%")) { + } elseif (($token === '~') || ($token === '%')) { // echo 'Token is a unary operator
'; if (is_null($arg = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); - if ($token === "_") { + $arg = $arg['value']; + if ($token === '~') { // echo 'Token is a negation operator
'; - $this->_writeDebug($cellID,'Evaluating Negation of '.self::_showValue($arg)); + $this->_writeDebug('Evaluating Negation of '.self::_showValue($arg)); $multiplier = -1; } else { // echo 'Token is a percentile operator
'; - $this->_writeDebug($cellID,'Evaluating Percentile of '.self::_showValue($arg)); + $this->_writeDebug('Evaluating Percentile of '.self::_showValue($arg)); $multiplier = 0.01; } if (is_array($arg)) { - self::_checkMatrixOperands($arg,$multiplier); + self::_checkMatrixOperands($arg,$multiplier,2); try { $matrix1 = new Matrix($arg); $matrixResult = $matrix1->arrayTimesEquals($multiplier); $result = $matrixResult->getArray(); } catch (Exception $ex) { - $this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage()); + $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); $result = '#VALUE!'; } - + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + $stack->push('Value',$result); } else { - $result = $multiplier * $arg; + $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack); } - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); - $stack->push($result); } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) { + $cellRef = null; // echo 'Element '.$token.' is a Cell reference
'; if (isset($matches[8])) { // echo 'Reference is a Range of cells
'; @@ -2574,15 +2714,16 @@ class PHPExcel_Calculation { } else { $cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10]; if ($matches[2] > '') { + $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug($cellID,'Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]); + $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]); $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false); - $this->_writeDebug($cellID,'Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; - $this->_writeDebug($cellID,'Evaluating Cell Range '.$cellRef.' in current worksheet'); + $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in current worksheet'); $cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false); - $this->_writeDebug($cellID,'Evaluation Result for cells '.$cellRef.' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cells '.$cellRef.' is '.self::_showTypeDetails($cellValue)); } } } else { @@ -2593,94 +2734,123 @@ class PHPExcel_Calculation { } else { $cellRef = $matches[6].$matches[7]; if ($matches[2] > '') { + $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug($cellID,'Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]); - if ($pCell->getParent()->cellExists($cellRef)) { + $this->_writeDebug('Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]); + if ($pCell->getParent()->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) { $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false); } else { - $cellValue = null; + $cellValue = PHPExcel_Calculation_Functions::REF(); } - $this->_writeDebug($cellID,'Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; - $this->_writeDebug($cellID,'Evaluating Cell '.$cellRef.' in current worksheet'); + $this->_writeDebug('Evaluating Cell '.$cellRef.' in current worksheet'); if ($pCell->getParent()->cellExists($cellRef)) { - $cellValue = $pCell->getParent()->getCell($cellRef)->getCalculatedValue(false); + $cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false); } else { - $cellValue = ''; + $cellValue = NULL; } - $this->_writeDebug($cellID,'Evaluation Result for cell '.$cellRef.' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cell '.$cellRef.' is '.self::_showTypeDetails($cellValue)); } } } - $stack->push($cellValue); + $stack->push('Value',$cellValue,$cellRef); // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on } elseif (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $token, $matches)) { // echo 'Token is a function
'; $functionName = $matches[1]; $argCount = $stack->pop(); + $argCount = $argCount['value']; if ($functionName != 'MKMATRIX') { - $this->_writeDebug($cellID,'Evaluating Function '.$functionName.'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); + $this->_writeDebug('Evaluating Function '.$functionName.'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); } - if ((array_key_exists($functionName, $this->_controlFunctions)) || (array_key_exists($functionName, $this->_PHPExcelFunctions))) { // function - if (array_key_exists($functionName, $this->_controlFunctions)) { - $functionCall = $this->_controlFunctions[$functionName]['functionCall']; - } elseif (array_key_exists($functionName, $this->_PHPExcelFunctions)) { + if ((array_key_exists($functionName, $this->_PHPExcelFunctions)) || (array_key_exists($functionName, $this->_controlFunctions))) { // function + if (array_key_exists($functionName, $this->_PHPExcelFunctions)) { $functionCall = $this->_PHPExcelFunctions[$functionName]['functionCall']; + $passByReference = isset($this->_PHPExcelFunctions[$functionName]['passByReference']); + $passCellReference = isset($this->_PHPExcelFunctions[$functionName]['passCellReference']); + } elseif (array_key_exists($functionName, $this->_controlFunctions)) { + $functionCall = $this->_controlFunctions[$functionName]['functionCall']; + $passByReference = isset($this->_controlFunctions[$functionName]['passByReference']); + $passCellReference = isset($this->_controlFunctions[$functionName]['passCellReference']); } // get the arguments for this function // echo 'Function '.$functionName.' expects '.$argCount.' arguments
'; - $args = array(); - for ($i = $argCount; $i > 0; --$i) { + $args = $argArrayVals = array(); + for ($i = 0; $i < $argCount; ++$i) { $arg = $stack->pop(); -// if (is_null($arg)) return $this->_raiseFormulaError("internal error"); - $args[$i] = $arg; + $a = $argCount - $i - 1; + if (($passByReference) && + (isset($this->_PHPExcelFunctions[$functionName]['passByReference'][$a])) && + ($this->_PHPExcelFunctions[$functionName]['passByReference'][$a])) { + if (is_null($arg['reference'])) { + $args[] = $cellID; + if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($cellID); } + } else { + $args[] = $arg['reference']; + if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($arg['reference']); } + } + } else { + $args[] = self::_unwrapResult($arg['value']); + if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($arg['value']); } + } } // Reverse the order of the arguments - ksort($args); + krsort($args); + if (($passByReference) && ($argCount == 0)) { + $args[] = $cellID; + $argArrayVals[] = self::_showValue($cellID); + } // echo 'Arguments are: '; // print_r($args); // echo '
'; if ($functionName != 'MKMATRIX') { - $argArrayVals = array(); - foreach($args as &$arg) { - $argArrayVals[] = self::_showValue($arg); - $arg = self::_unwrapResult($arg); - } - unset($arg); - $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.implode(', ',$argArrayVals).' )'); + krsort($argArrayVals); + $this->_writeDebug('Evaluating '. $functionName.'( '.implode(', ',$argArrayVals).' )'); } // Process each argument in turn, building the return value as an array // if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) { // $operand1 = $args[1]; -// $this->_writeDebug($cellID,'Argument is a matrix: '.self::_showValue($operand1)); +// $this->_writeDebug('Argument is a matrix: '.self::_showValue($operand1)); // $result = array(); // $row = 0; // foreach($operand1 as $args) { // if (is_array($args)) { // foreach($args as $arg) { -// $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.self::_showValue($arg).' )'); +// $this->_writeDebug('Evaluating '. $functionName.'( '.self::_showValue($arg).' )'); // $r = call_user_func_array($functionCall,$arg); -// $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($r)); +// $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($r)); // $result[$row][] = $r; // } // ++$row; // } else { -// $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.self::_showValue($args).' )'); +// $this->_writeDebug('Evaluating '. $functionName.'( '.self::_showValue($args).' )'); // $r = call_user_func_array($functionCall,$args); -// $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($r)); +// $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($r)); // $result[] = $r; // } // } // } else { // Process the argument with the appropriate function call - $result = call_user_func_array($functionCall,$args); + if ($passCellReference) { + $args[] = $pCell; + } + if (strpos($functionCall,'::') !== false) { + $result = call_user_func_array(explode('::',$functionCall),$args); + } else { + foreach($args as &$arg) { + $arg = PHPExcel_Calculation_Functions::flattenSingleValue($arg); + } + unset($arg); + $result = call_user_func_array($functionCall,$args); + } // } if ($functionName != 'MKMATRIX') { - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); } - $stack->push(self::_wrapResult($result)); + $stack->push('Value',self::_wrapResult($result)); } } else { @@ -2688,20 +2858,20 @@ class PHPExcel_Calculation { if (array_key_exists(strtoupper($token), $this->_ExcelConstants)) { $excelConstant = strtoupper($token); // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; - $stack->push($this->_ExcelConstants[$excelConstant]); - $this->_writeDebug($cellID,'Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails($this->_ExcelConstants[$excelConstant])); - } elseif ((is_null($token)) || ($token == '') || (is_bool($token)) || (is_numeric($token)) || ($token{0} == '"') || ($token{0} == '#')) { -// echo 'Token is a number, boolean, string or an Excel error
'; - $stack->push($token); - // if the token is a constant, push the constant value on the stack + $stack->push('Constant Value',$this->_ExcelConstants[$excelConstant]); + $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails($this->_ExcelConstants[$excelConstant])); + } elseif ((is_numeric($token)) || (is_bool($token)) || (is_null($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { +// echo 'Token is a number, boolean, string, null or an Excel error
'; + $stack->push('Value',$token); + // if the token is a named range, push the named range name onto the stack } elseif (preg_match('/^'.self::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $token, $matches)) { // echo 'Token is a named range
'; $namedRange = $matches[6]; // echo 'Named Range is '.$namedRange.'
'; - $this->_writeDebug($cellID,'Evaluating Named Range '.$namedRange); - $cellValue = $this->extractNamedRange($namedRange, $pCell->getParent(), false); - $this->_writeDebug($cellID,'Evaluation Result for named range '.$namedRange.' is '.self::_showTypeDetails($cellValue)); - $stack->push($cellValue); + $this->_writeDebug('Evaluating Named Range '.$namedRange); + $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCell->getParent() : null), false); + $this->_writeDebug('Evaluation Result for named range '.$namedRange.' is '.self::_showTypeDetails($cellValue)); + $stack->push('Named Range',$cellValue,$namedRange); } else { return $this->_raiseFormulaError("undefined variable '$token'"); } @@ -2710,9 +2880,11 @@ class PHPExcel_Calculation { // when we're out of tokens, the stack should have a single element, the final result if ($stack->count() != 1) return $this->_raiseFormulaError("internal error"); $output = $stack->pop(); - if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { - return array_unshift(array_unshift($output)); - } + $output = $output['value']; + +// if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { +// return array_shift(PHPExcel_Calculation_Functions::flattenArray($output)); +// } return $output; } // function _processTokenStack() @@ -2722,18 +2894,18 @@ class PHPExcel_Calculation { if (is_string($operand)) { // We only need special validations for the operand if it is a string // Start by stripping off the quotation marks we use to identify true excel string values internally - if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand,'"'); } + if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand); } // If the string is a numeric value, we treat it as a numeric, so no further testing if (!is_numeric($operand)) { // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations if ($operand > '' && $operand{0} == '#') { - $stack->push($operand); - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($operand)); + $stack->push('Value', $operand); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($operand)); return false; - } else { - // If not a numeric, then it's a text string, and so can't be used in mathematical binary operations - $stack->push('#VALUE!'); - $this->_writeDebug($cellID,'Evaluation Result is a '.self::_showTypeDetails('#VALUE!')); + } elseif (!PHPExcel_Shared_String::convertToNumberIfFraction($operand)) { + // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations + $stack->push('Value', '#VALUE!'); + $this->_writeDebug('Evaluation Result is a '.self::_showTypeDetails('#VALUE!')); return false; } } @@ -2744,10 +2916,45 @@ class PHPExcel_Calculation { } // function _validateBinaryOperand() - private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack) { - // Validate the two operands + private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack,$recursingArrays=false) { + // If we're dealing with matrix operations, we want a matrix result + if ((is_array($operand1)) || (is_array($operand2))) { + $result = array(); + if ((is_array($operand1)) && (!is_array($operand2))) { + foreach($operand1 as $x => $operandData) { + $this->_writeDebug('Evaluating '.self::_showValue($operandData).' '.$operation.' '.self::_showValue($operand2)); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } elseif ((!is_array($operand1)) && (is_array($operand2))) { + foreach($operand2 as $x => $operandData) { + $this->_writeDebug('Evaluating '.self::_showValue($operand1).' '.$operation.' '.self::_showValue($operandData)); + $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } else { + if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); } + foreach($operand1 as $x => $operandData) { + $this->_writeDebug('Evaluating '.self::_showValue($operandData).' '.$operation.' '.self::_showValue($operand2[$x])); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,True); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } + // Log the result details + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + // And push the result onto the stack + $stack->push('Array',$result); + return true; + } - // If we're dealing with non-matrix operations, execute the necessary operation + // Simple validate the two operands if they are string values + if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); } + if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); } + + // execute the necessary operation switch ($operation) { // Greater than case '>': @@ -2776,12 +2983,13 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); // And push the result onto the stack - $stack->push($result); + $stack->push('Value',$result); return true; } // function _executeBinaryComparisonOperation() + private function _executeNumericBinaryOperation($cellID,$operand1,$operand2,$operation,$matrixFunction,&$stack) { // Validate the two operands if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return false; @@ -2792,7 +3000,7 @@ class PHPExcel_Calculation { // matrix operation if ((is_array($operand1)) || (is_array($operand2))) { // Ensure that both operands are arrays/matrices - self::_checkMatrixOperands($operand1,$operand2); + self::_checkMatrixOperands($operand1,$operand2,2); try { // Convert operand 1 from a PHP array to a matrix $matrix = new Matrix($operand1); @@ -2800,7 +3008,7 @@ class PHPExcel_Calculation { $matrixResult = $matrix->$matrixFunction($operand2); $result = $matrixResult->getArray(); } catch (Exception $ex) { - $this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage()); + $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); $result = '#VALUE!'; } } else { @@ -2822,8 +3030,8 @@ class PHPExcel_Calculation { case '/': if ($operand2 == 0) { // Trap for Divide by Zero error - $stack->push('#DIV/0!'); - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails('#DIV/0!')); + $stack->push('Value','#DIV/0!'); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails('#DIV/0!')); return false; } else { $result = $operand1/$operand2; @@ -2837,19 +3045,17 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); // And push the result onto the stack - $stack->push($result); + $stack->push('Value',$result); return true; } // function _executeNumericBinaryOperation() - private function _writeDebug($cellID,$message) { + private function _writeDebug($message) { // Only write the debug log if logging is enabled if ($this->writeDebugLog) { -// $prefix = substr(implode(' -> ',$this->debugLogStack).' -> ',4+strlen($this->debugLogStack[0])); - $prefix = implode(' -> ',$this->debugLogStack).' -> '; - $this->debugLog[] = $prefix.$message; + $this->debugLog[] = implode(' -> ',$this->debugLogStack).' -> '.$message; } } // function _writeDebug() @@ -2857,6 +3063,7 @@ class PHPExcel_Calculation { // trigger an error, but nicely, if need be private function _raiseFormulaError($errorMessage) { $this->formulaError = $errorMessage; + echo '_raiseFormulaError message is '.$errorMessage.'
'; if (!$this->suppressFormulaErrors) throw new Exception($errorMessage); trigger_error($errorMessage, E_USER_ERROR); } // function _raiseFormulaError() @@ -2865,20 +3072,18 @@ class PHPExcel_Calculation { /** * Extract range values * - * @param string $pRange String based range representation + * @param string &$pRange String based range representation * @param PHPExcel_Worksheet $pSheet Worksheet * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. * @throws Exception */ - public function extractCellRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { + public function extractCellRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { // Return value - $returnValue = array ( ); + $returnValue = array (); // echo 'extractCellRange('.$pRange.')
'; - // Worksheet given? if (!is_null($pSheet)) { - // Worksheet reference? -// echo 'Current sheet name is '.$pSheet->getTitle().'
'; +// echo 'Passed sheet name is '.$pSheet->getTitle().'
'; // echo 'Range reference is '.$pRange.'
'; if (strpos ($pRange, '!') !== false) { // echo '$pRange reference includes sheet reference
'; @@ -2891,16 +3096,26 @@ class PHPExcel_Calculation { // Extract range $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + $pRange = $pSheet->getTitle().'!'.$pRange; if (count($aReferences) == 1) { - return $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); - } + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]); + if ($pSheet->cellExists($aReferences[0])) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } else { + // Extract cell data + foreach ($aReferences as $reference) { + // Extract range + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); - // Extract cell data - foreach ($aReferences as $reference) { - // Extract range - list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); - - $returnValue[$currentCol][$currentRow] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + if ($pSheet->cellExists($reference)) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } } } @@ -2912,19 +3127,17 @@ class PHPExcel_Calculation { /** * Extract range values * - * @param string $pRange String based range representation + * @param string &$pRange String based range representation * @param PHPExcel_Worksheet $pSheet Worksheet * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. * @throws Exception */ - public function extractNamedRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { + public function extractNamedRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { // Return value - $returnValue = array ( ); + $returnValue = array (); // echo 'extractNamedRange('.$pRange.')
'; - // Worksheet given? if (!is_null($pSheet)) { - // Worksheet reference? // echo 'Current sheet name is '.$pSheet->getTitle().'
'; // echo 'Range reference is '.$pRange.'
'; if (strpos ($pRange, '!') !== false) { @@ -2949,29 +3162,33 @@ class PHPExcel_Calculation { return $returnValue; } } + } else { + return PHPExcel_Calculation_Functions::REF(); } // Extract range $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); if (count($aReferences) == 1) { - return $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]); + if ($pSheet->cellExists($aReferences[0])) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } else { + // Extract cell data + foreach ($aReferences as $reference) { + // Extract range + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); +// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
'; + if ($pSheet->cellExists($reference)) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } } - - // Extract cell data - foreach ($aReferences as $reference) { - // Extract range - list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); -// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
'; - $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); - } -// print_r($returnValue); -// echo '
'; - $returnValue = array_values($returnValue); - foreach($returnValue as &$rr) { - $rr = array_values($rr); - } - unset($rr); -// print_r($returnValue); +// print_r($returnValue); // echo '
'; } @@ -2988,7 +3205,7 @@ class PHPExcel_Calculation { */ public function isImplemented($pFunction = '') { $pFunction = strtoupper ($pFunction); - if (isset ($this->_PHPExcelFunctions[$pFunction])) { + if (isset($this->_PHPExcelFunctions[$pFunction])) { return ($this->_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY'); } else { return false; @@ -3025,15 +3242,7 @@ class PHPExcel_Calculation { * @return array */ public function listFunctionNames() { - // Return value - $returnValue = array(); - // Loop functions - foreach ($this->_PHPExcelFunctions as $functionName => $function) { - $returnValue[] = $functionName; - } - - // Return - return $returnValue; + return array_keys($this->_PHPExcelFunctions); } // function listFunctionNames() } // class PHPExcel_Calculation @@ -3047,27 +3256,35 @@ class PHPExcel_Token_Stack { private $_stack = array(); private $_count = 0; + public function count() { return $this->_count; - } + } // function count() + + + public function push($type,$value,$reference=null) { + $this->_stack[$this->_count++] = array('type' => $type, + 'value' => $value, + 'reference' => $reference + ); + } // function push() - public function push($value) { - $this->_stack[$this->_count++] = $value; - } public function pop() { if ($this->_count > 0) { return $this->_stack[--$this->_count]; } return null; - } + } // function pop() + public function last($n=1) { if ($this->_count-$n < 0) { return null; } return $this->_stack[$this->_count-$n]; - } + } // function last() + function __construct() { } diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Exception.php b/libraries/PHPExcel/PHPExcel/Calculation/Exception.php index 36ea5e08a..84cf09d79 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Exception.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Exception.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Exception extends Exception { /** diff --git a/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php b/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php index 734c4a611..48475df5c 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ @@ -41,7 +41,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Exception.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_ExceptionHandler { /** diff --git a/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php b/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php index 648e93983..d6bf785ad 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -65,7 +65,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaToken.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_FormulaParser { /* Character constants */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php b/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php index dff57675c..091e69d0b 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ PARTLY BASED ON: * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_FormulaToken { /* Token types */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Function.php b/libraries/PHPExcel/PHPExcel/Calculation/Function.php index 7b0c6c175..6ea8aea10 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Function.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Function.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Function { /* Function categories */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Functions.php b/libraries/PHPExcel/PHPExcel/Calculation/Functions.php index 8d6ca3d05..2ba67fd77 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Functions.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Functions.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -38,14 +38,21 @@ define('LOG_GAMMA_X_MAX_VALUE', 2.55e305); /** SQRT2PI */ define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099); +/** 2 / PI */ +define('M_2DIVPI', 0.63661977236758134307553505349006); + /** XMININ */ define('XMININ', 2.23e-308); /** MAX_ITERATIONS */ -define('MAX_ITERATIONS', 150); +define('MAX_ITERATIONS', 256); +/** FINANCIAL_MAX_ITERATIONS */ +define('FINANCIAL_MAX_ITERATIONS', 128); /** PRECISION */ define('PRECISION', 8.88E-016); +/** FINANCIAL_PRECISION */ +define('FINANCIAL_PRECISION', 1.0e-08); /** EULER */ define('EULER', 2.71828182845904523536); @@ -67,6 +74,9 @@ if (!defined('PHPEXCEL_ROOT')) { /** PHPExcel_Cell */ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; +/** PHPExcel_Calculation */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; + /** PHPExcel_Cell_DataType */ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; @@ -86,7 +96,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Functions { @@ -271,21 +281,48 @@ class PHPExcel_Calculation_Functions { } // function REF() + /** + * VALUE + * + * @access public + * @category Error Returns + * @return string #VALUE! + */ + public static function VALUE() { + return self::$_errorCodes['value']; + } // function VALUE() + + + private static function isMatrixValue($idx) { + return ((substr_count($idx,'.') <= 1) || (preg_match('/\.[A-Z]/',$idx) > 0)); + } + + + private static function isValue($idx) { + return (substr_count($idx,'.') == 0); + } + + + private static function isCellValue($idx) { + return (substr_count($idx,'.') > 1); + } + + /** * LOGICAL_AND * * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE. * * Excel Function: - * AND(logical1[,logical2[, ...]]) + * =AND(logical1[,logical2[, ...]]) * * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays * or references that contain logical values. * - * Booleans arguments are treated as True or False as appropriate + * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds the value TRUE or FALSE, - * holds the value TRUE or FALSE, in which case it is evaluated as a boolean + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value * * @access public * @category Logical Functions @@ -303,10 +340,8 @@ class PHPExcel_Calculation_Functions { // Is it a boolean value? if (is_bool($arg)) { $returnValue = $returnValue && $arg; - ++$argCount; } elseif ((is_numeric($arg)) && (!is_string($arg))) { $returnValue = $returnValue && ($arg != 0); - ++$argCount; } elseif (is_string($arg)) { $arg = strtoupper($arg); if ($arg == 'TRUE') { @@ -317,8 +352,8 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } $returnValue = $returnValue && ($arg != 0); - ++$argCount; } + ++$argCount; } // Return @@ -335,15 +370,15 @@ class PHPExcel_Calculation_Functions { * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE. * * Excel Function: - * OR(logical1[,logical2[, ...]]) + * =OR(logical1[,logical2[, ...]]) * * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays * or references that contain logical values. * - * Booleans arguments are treated as True or False as appropriate + * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string - * holds the value TRUE or FALSE, in which case it is evaluated as a boolean + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value * * @access public * @category Logical Functions @@ -361,10 +396,8 @@ class PHPExcel_Calculation_Functions { // Is it a boolean value? if (is_bool($arg)) { $returnValue = $returnValue || $arg; - ++$argCount; } elseif ((is_numeric($arg)) && (!is_string($arg))) { $returnValue = $returnValue || ($arg != 0); - ++$argCount; } elseif (is_string($arg)) { $arg = strtoupper($arg); if ($arg == 'TRUE') { @@ -375,8 +408,8 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } $returnValue = $returnValue || ($arg != 0); - ++$argCount; } + ++$argCount; } // Return @@ -393,7 +426,7 @@ class PHPExcel_Calculation_Functions { * Returns the boolean FALSE. * * Excel Function: - * FALSE() + * =FALSE() * * @access public * @category Logical Functions @@ -410,7 +443,7 @@ class PHPExcel_Calculation_Functions { * Returns the boolean TRUE. * * Excel Function: - * TRUE() + * =TRUE() * * @access public * @category Logical Functions @@ -427,7 +460,14 @@ class PHPExcel_Calculation_Functions { * Returns the boolean inverse of the argument. * * Excel Function: - * NOT(logical) + * =NOT(logical) + * + * The argument must evaluate to a logical value such as TRUE or FALSE + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value * * @access public * @category Logical Functions @@ -435,6 +475,18 @@ class PHPExcel_Calculation_Functions { * @return boolean The boolean inverse of the argument. */ public static function LOGICAL_NOT($logical) { + $logical = self::flattenSingleValue($logical); + if (is_string($logical)) { + $logical = strtoupper($logical); + if ($logical == 'TRUE') { + return False; + } elseif ($logical == 'FALSE') { + return True; + } else { + return self::$_errorCodes['value']; + } + } + return !$logical; } // function LOGICAL_NOT() @@ -445,7 +497,7 @@ class PHPExcel_Calculation_Functions { * Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE. * * Excel Function: - * IF(condition[,returnIfTrue[,returnIfFalse]]) + * =IF(condition[,returnIfTrue[,returnIfFalse]]) * * Condition is any value or expression that can be evaluated to TRUE or FALSE. * For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100, @@ -464,17 +516,17 @@ class PHPExcel_Calculation_Functions { * If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. * ReturnIfFalse can be another formula. * + * @access public + * @category Logical Functions * @param mixed $condition Condition to evaluate * @param mixed $returnIfTrue Value to return when condition is true - * @param mixed $returnIfFalse Value to return when condition is false + * @param mixed $returnIfFalse Optional value to return when condition is false * @return mixed The value of returnIfTrue or returnIfFalse determined by condition */ public static function STATEMENT_IF($condition = true, $returnIfTrue = 0, $returnIfFalse = False) { - $condition = self::flattenSingleValue($condition); - $returnIfTrue = self::flattenSingleValue($returnIfTrue); - $returnIfFalse = self::flattenSingleValue($returnIfFalse); - if (is_null($returnIfTrue)) { $returnIfTrue = 0; } - if (is_null($returnIfFalse)) { $returnIfFalse = 0; } + $condition = (is_null($condition)) ? True : (boolean) self::flattenSingleValue($condition); + $returnIfTrue = (is_null($returnIfTrue)) ? 0 : self::flattenSingleValue($returnIfTrue); + $returnIfFalse = (is_null($returnIfFalse)) ? False : self::flattenSingleValue($returnIfFalse); return ($condition ? $returnIfTrue : $returnIfFalse); } // function STATEMENT_IF() @@ -483,12 +535,20 @@ class PHPExcel_Calculation_Functions { /** * STATEMENT_IFERROR * - * @param mixed $value Value to check , is also value when no error - * @param mixed $errorpart Value when error - * @return mixed + * Excel Function: + * =IFERROR(testValue,errorpart) + * + * @access public + * @category Logical Functions + * @param mixed $testValue Value to check, is also the value returned when no error + * @param mixed $errorpart Value to return when testValue is an error condition + * @return mixed The value of errorpart or testValue determined by error condition */ - public static function STATEMENT_IFERROR($value = '', $errorpart = '') { - return self::STATEMENT_IF(self::IS_ERROR($value), $errorpart, $value); + public static function STATEMENT_IFERROR($testValue = '', $errorpart = '') { + $testValue = (is_null($testValue)) ? '' : self::flattenSingleValue($testValue); + $errorpart = (is_null($errorpart)) ? '' : self::flattenSingleValue($errorpart); + + return self::STATEMENT_IF(self::IS_ERROR($testValue), $errorpart, $testValue); } // function STATEMENT_IFERROR() @@ -542,7 +602,7 @@ class PHPExcel_Calculation_Functions { */ public static function LOG_BASE($number, $base=10) { $number = self::flattenSingleValue($number); - $base = self::flattenSingleValue($base); + $base = (is_null($base)) ? 10 : (float) self::flattenSingleValue($base); return log($number, $base); } // function LOG_BASE() @@ -596,12 +656,12 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { - $returnValue += pow($arg,2); + $returnValue += ($arg * $arg); } } @@ -627,7 +687,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -666,7 +726,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -706,7 +766,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -785,9 +845,9 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); // Calculate - $n = array_pop($aArgs); + $entry = array_pop($aArgs); - if ((is_numeric($n)) && (!is_string($n))) { + if ((is_numeric($entry)) && (!is_string($entry))) { $mArgs = array(); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -796,12 +856,12 @@ class PHPExcel_Calculation_Functions { } } $count = self::COUNT($mArgs); - $n = floor(--$n); - if (($n < 0) || ($n >= $count) || ($count == 0)) { + $entry = floor(--$entry); + if (($entry < 0) || ($entry >= $count) || ($count == 0)) { return self::$_errorCodes['num']; } sort($mArgs); - return $mArgs[$n]; + return $mArgs[$entry]; } return self::$_errorCodes['value']; } // function SMALL() @@ -825,7 +885,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -905,9 +965,9 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); // Calculate - $n = floor(array_pop($aArgs)); + $entry = floor(array_pop($aArgs)); - if ((is_numeric($n)) && (!is_string($n))) { + if ((is_numeric($entry)) && (!is_string($entry))) { $mArgs = array(); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -916,12 +976,12 @@ class PHPExcel_Calculation_Functions { } } $count = self::COUNT($mArgs); - $n = floor(--$n); - if (($n < 0) || ($n >= $count) || ($count == 0)) { + $entry = floor(--$entry); + if (($entry < 0) || ($entry >= $count) || ($count == 0)) { return self::$_errorCodes['num']; } rsort($mArgs); - return $mArgs[$n]; + return $mArgs[$entry]; } return self::$_errorCodes['value']; } // function LARGE() @@ -1025,11 +1085,12 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments - $aArgs = self::flattenArray(func_get_args()); - foreach ($aArgs as $arg) { - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { - $arg = (int) $arg; + // Loop through arguments + $aArgs = self::flattenArrayIndexed(func_get_args()); + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { @@ -1059,7 +1120,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a blank cell? @@ -1123,9 +1184,15 @@ class PHPExcel_Calculation_Functions { $returnValue = 0; $aArgs = self::flattenArray($aArgs); + $condition = self::flattenSingleValue($condition); if (!in_array($condition{0},array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } $condition = '='.$condition; + } else { + preg_match('/([<>=]+)(.*)/',$condition,$matches); + list(,$operator,$operand) = $matches; + if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + $condition = $operator.$operand; } // Loop through arguments foreach ($aArgs as $arg) { @@ -1168,6 +1235,11 @@ class PHPExcel_Calculation_Functions { if (!in_array($condition{0},array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } $condition = '='.$condition; + } else { + preg_match('/([<>=]+)(.*)/',$condition,$matches); + list(,$operator,$operand) = $matches; + if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + $condition = $operator.$operand; } // Loop through arguments foreach ($aArgs as $key => $arg) { @@ -1198,14 +1270,13 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function AVERAGE() { - // Return value - $returnValue = 0; + $aArgs = self::flattenArrayIndexed(func_get_args()); + $returnValue = $aCount = 0; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); - $aCount = 0; - foreach ($aArgs as $arg) { - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { $arg = (integer) $arg; } // Is it a numeric value? @@ -1246,21 +1317,25 @@ class PHPExcel_Calculation_Functions { $returnValue = null; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $aCount = 0; - foreach ($aArgs as $arg) { - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = $arg; + } else { + $returnValue += $arg; + } + ++$aCount; } - if (is_null($returnValue)) { - $returnValue = $arg; - } else { - $returnValue += $arg; - } - ++$aCount; } } @@ -1402,18 +1477,19 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function DEVSQ() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGE(func_get_args()); - if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - + $aMean = self::AVERAGE($aArgs); + if ($aMean != self::$_errorCodes['divisionbyzero']) { $aCount = -1; - foreach ($aArgs as $arg) { + foreach ($aArgs as $k => $arg) { // Is it a numeric value? - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { - $arg = (int) $arg; + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; } if ((is_numeric($arg)) && (!is_string($arg))) { if (is_null($returnValue)) { @@ -1451,7 +1527,7 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function AVEDEV() { - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); // Return value $returnValue = null; @@ -1459,8 +1535,9 @@ class PHPExcel_Calculation_Functions { $aMean = self::AVERAGE($aArgs); if ($aMean != self::$_errorCodes['divisionbyzero']) { $aCount = 0; - foreach ($aArgs as $arg) { - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { $arg = (integer) $arg; } // Is it a numeric value? @@ -1475,7 +1552,10 @@ class PHPExcel_Calculation_Functions { } // Return - return $returnValue / $aCount ; + if ($aCount == 0) { + return self::$_errorCodes['divisionbyzero']; + } + return $returnValue / $aCount; } return self::$_errorCodes['num']; } // function AVEDEV() @@ -1497,9 +1577,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function GEOMEAN() { - $aMean = self::PRODUCT(func_get_args()); + $aArgs = self::flattenArray(func_get_args()); + + $aMean = self::PRODUCT($aArgs); if (is_numeric($aMean) && ($aMean > 0)) { - $aArgs = self::flattenArray(func_get_args()); $aCount = self::COUNT($aArgs) ; if (self::MIN($aArgs) > 0) { return pow($aMean, (1 / $aCount)); @@ -1617,15 +1698,19 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEV() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGE(func_get_args()); + $aMean = self::AVERAGE($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = -1; - foreach ($aArgs as $arg) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { if (is_null($returnValue)) { @@ -1660,28 +1745,32 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEVA() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGEA(func_get_args()); + $aMean = self::AVERAGEA($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = -1; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; } - if (is_null($returnValue)) { - $returnValue = pow(($arg - $aMean),2); - } else { - $returnValue += pow(($arg - $aMean),2); - } - ++$aCount; } } @@ -1708,15 +1797,19 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEVP() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGE(func_get_args()); + $aMean = self::AVERAGE($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = 0; - foreach ($aArgs as $arg) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { if (is_null($returnValue)) { @@ -1751,28 +1844,32 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEVPA() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGEA(func_get_args()); + $aMean = self::AVERAGEA($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = 0; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; } - if (is_null($returnValue)) { - $returnValue = pow(($arg - $aMean),2); - } else { - $returnValue += pow(($arg - $aMean),2); - } - ++$aCount; } } @@ -1808,6 +1905,7 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); $aCount = 0; foreach ($aArgs as $arg) { + if (is_bool($arg)) { $arg = (integer) $arg; } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { $summerA += ($arg * $arg); @@ -1818,8 +1916,8 @@ class PHPExcel_Calculation_Functions { // Return if ($aCount > 1) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); } return $returnValue; @@ -1846,26 +1944,33 @@ class PHPExcel_Calculation_Functions { $summerA = $summerB = 0; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $aCount = 0; - foreach ($aArgs as $arg) { - // Is it a numeric value? + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && + (self::isValue($k))) { + return self::$_errorCodes['value']; + } elseif ((is_string($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; } - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; } } // Return if ($aCount > 1) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); } return $returnValue; @@ -1895,6 +2000,7 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); $aCount = 0; foreach ($aArgs as $arg) { + if (is_bool($arg)) { $arg = (integer) $arg; } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { $summerA += ($arg * $arg); @@ -1905,8 +2011,8 @@ class PHPExcel_Calculation_Functions { // Return if ($aCount > 0) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * $aCount); } return $returnValue; @@ -1933,26 +2039,33 @@ class PHPExcel_Calculation_Functions { $summerA = $summerB = 0; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $aCount = 0; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && + (self::isValue($k))) { + return self::$_errorCodes['value']; + } elseif ((is_string($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; } - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; } } // Return if ($aCount > 0) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * $aCount); } return $returnValue; @@ -1972,7 +2085,7 @@ class PHPExcel_Calculation_Functions { public static function RANK($value,$valueSet,$order=0) { $value = self::flattenSingleValue($value); $valueSet = self::flattenArray($valueSet); - $order = self::flattenSingleValue($order); + $order = (is_null($order)) ? 0 : (integer) self::flattenSingleValue($order); foreach($valueSet as $key => $valueEntry) { if (!is_numeric($valueEntry)) { @@ -2005,9 +2118,9 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function PERCENTRANK($valueSet,$value,$significance=3) { - $valueSet = self::flattenArray($valueSet); - $value = self::flattenSingleValue($value); - $significance = self::flattenSingleValue($significance); + $valueSet = self::flattenArray($valueSet); + $value = self::flattenSingleValue($value); + $significance = (is_null($significance)) ? 3 : (integer) self::flattenSingleValue($significance); foreach($valueSet as $key => $valueEntry) { if (!is_numeric($valueEntry)) { @@ -2040,20 +2153,29 @@ class PHPExcel_Calculation_Functions { } // function PERCENTRANK() - private static function _checkTrendArray($values) { - foreach($values as $key => $value) { - if ((is_bool($value)) || ((is_string($value)) && (trim($value) == ''))) { - unset($values[$key]); - } elseif (is_string($value)) { - if (is_numeric($value)) { - $values[$key] = (float) $value; - } else { - unset($values[$key]); - } + private static function _checkTrendArrays(&$array1,&$array2) { + if (!is_array($array1)) { $array1 = array($array1); } + if (!is_array($array2)) { $array2 = array($array2); } + + $array1 = self::flattenArray($array1); + $array2 = self::flattenArray($array2); + foreach($array1 as $key => $value) { + if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { + unset($array1[$key]); + unset($array2[$key]); } } - return $values; - } // function _checkTrendArray() + foreach($array2 as $key => $value) { + if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { + unset($array1[$key]); + unset($array2[$key]); + } + } + $array1 = array_merge($array1); + $array2 = array_merge($array2); + + return True; + } // function _checkTrendArrays() /** @@ -2066,12 +2188,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function INTERCEPT($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2095,12 +2215,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function RSQ($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2124,12 +2242,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function SLOPE($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2153,12 +2269,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STEYX($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2182,12 +2296,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function COVAR($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2210,13 +2322,14 @@ class PHPExcel_Calculation_Functions { * @param array of mixed Data Series X * @return float */ - public static function CORREL($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + public static function CORREL($yValues,$xValues=null) { + if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) { + return self::$_errorCodes['value']; + } + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2242,21 +2355,22 @@ class PHPExcel_Calculation_Functions { * @param boolean A logical value specifying whether to return additional regression statistics. * @return array */ - public static function LINEST($yValues,$xValues,$const=True,$stats=False) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - $const = (boolean) self::flattenSingleValue($const); - $stats = (boolean) self::flattenSingleValue($stats); + public static function LINEST($yValues,$xValues=null,$const=True,$stats=False) { + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); + $stats = (is_null($stats)) ? False : (boolean) self::flattenSingleValue($stats); + if (is_null($xValues)) $xValues = range(1,count(self::flattenArray($yValues))); - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { return self::$_errorCodes['na']; } elseif ($yValueCount == 1) { - return self::$_errorCodes['divisionbyzero']; + return 0; } $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const); @@ -2294,21 +2408,28 @@ class PHPExcel_Calculation_Functions { * @param boolean A logical value specifying whether to return additional regression statistics. * @return array */ - public static function LOGEST($yValues,$xValues,$const=True,$stats=False) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - $const = (boolean) self::flattenSingleValue($const); - $stats = (boolean) self::flattenSingleValue($stats); + public static function LOGEST($yValues,$xValues=null,$const=True,$stats=False) { + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); + $stats = (is_null($stats)) ? False : (boolean) self::flattenSingleValue($stats); + if (is_null($xValues)) $xValues = range(1,count(self::flattenArray($yValues))); - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); + foreach($yValues as $value) { + if ($value <= 0.0) { + return self::$_errorCodes['num']; + } + } + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { return self::$_errorCodes['na']; } elseif ($yValueCount == 1) { - return self::$_errorCodes['divisionbyzero']; + return 1; } $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const); @@ -2346,16 +2467,14 @@ class PHPExcel_Calculation_Functions { */ public static function FORECAST($xValue,$yValues,$xValues) { $xValue = self::flattenSingleValue($xValue); - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - if (!is_numeric($xValue)) { return self::$_errorCodes['value']; } - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2384,7 +2503,7 @@ class PHPExcel_Calculation_Functions { $yValues = self::flattenArray($yValues); $xValues = self::flattenArray($xValues); $newValues = self::flattenArray($newValues); - $const = (boolean) self::flattenSingleValue($const); + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const); if (count($newValues) == 0) { @@ -2415,7 +2534,7 @@ class PHPExcel_Calculation_Functions { $yValues = self::flattenArray($yValues); $xValues = self::flattenArray($xValues); $newValues = self::flattenArray($newValues); - $const = (boolean) self::flattenSingleValue($const); + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const); if (count($newValues) == 0) { @@ -2438,6 +2557,7 @@ class PHPExcel_Calculation_Functions { public static function ROMAN($aValue, $style=0) { $aValue = (integer) self::flattenSingleValue($aValue); + $style = (is_null($style)) ? 0 : (integer) self::flattenSingleValue($style); if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) { return self::$_errorCodes['value']; } @@ -2464,14 +2584,14 @@ class PHPExcel_Calculation_Functions { /** - * SUBTOTAL + * SUBTOTAL * - * Returns a subtotal in a list or database. + * Returns a subtotal in a list or database. * - * @param int the number 1 to 11 that specifies which function to + * @param int the number 1 to 11 that specifies which function to * use in calculating subtotals within a list. - * @param array of mixed Data Series - * @return float + * @param array of mixed Data Series + * @return float */ public static function SUBTOTAL() { $aArgs = self::flattenArray(func_get_args()); @@ -2521,12 +2641,12 @@ class PHPExcel_Calculation_Functions { /** - * SQRTPI + * SQRTPI * - * Returns the square root of (number * pi). + * Returns the square root of (number * pi). * - * @param float $number Number - * @return float Square Root of Number * Pi + * @param float $number Number + * @return float Square Root of Number * Pi */ public static function SQRTPI($number) { $number = self::flattenSingleValue($number); @@ -2535,19 +2655,19 @@ class PHPExcel_Calculation_Functions { if ($number < 0) { return self::$_errorCodes['num']; } - return sqrt($number * pi()) ; + return sqrt($number * M_PI) ; } return self::$_errorCodes['value']; } // function SQRTPI() /** - * FACT + * FACT * - * Returns the factorial of a number. + * Returns the factorial of a number. * - * @param float $factVal Factorial Value - * @return int Factorial + * @param float $factVal Factorial Value + * @return int Factorial */ public static function FACT($factVal) { $factVal = self::flattenSingleValue($factVal); @@ -2562,6 +2682,7 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } } + $factorial = 1; while ($factLoop > 1) { $factorial *= $factLoop--; @@ -2573,12 +2694,12 @@ class PHPExcel_Calculation_Functions { /** - * FACTDOUBLE + * FACTDOUBLE * - * Returns the double factorial of a number. + * Returns the double factorial of a number. * - * @param float $factVal Factorial Value - * @return int Double Factorial + * @param float $factVal Factorial Value + * @return int Double Factorial */ public static function FACTDOUBLE($factVal) { $factLoop = floor(self::flattenSingleValue($factVal)); @@ -2599,12 +2720,12 @@ class PHPExcel_Calculation_Functions { /** - * MULTINOMIAL + * MULTINOMIAL * - * Returns the ratio of the factorial of a sum of values to the product of factorials. + * Returns the ratio of the factorial of a sum of values to the product of factorials. * - * @param array of mixed Data Series - * @return float + * @param array of mixed Data Series + * @return float */ public static function MULTINOMIAL() { // Loop through arguments @@ -2634,13 +2755,13 @@ class PHPExcel_Calculation_Functions { /** - * CEILING + * CEILING * - * Returns number rounded up, away from zero, to the nearest multiple of significance. + * Returns number rounded up, away from zero, to the nearest multiple of significance. * - * @param float $number Number to round - * @param float $significance Significance - * @return float Rounded Number + * @param float $number Number to round + * @param float $significance Significance + * @return float Rounded Number */ public static function CEILING($number,$significance=null) { $number = self::flattenSingleValue($number); @@ -2665,12 +2786,12 @@ class PHPExcel_Calculation_Functions { /** - * EVEN + * EVEN * - * Returns number rounded up to the nearest even integer. + * Returns number rounded up to the nearest even integer. * - * @param float $number Number to round - * @return int Rounded Number + * @param float $number Number to round + * @return int Rounded Number */ public static function EVEN($number) { $number = self::flattenSingleValue($number); @@ -2684,12 +2805,12 @@ class PHPExcel_Calculation_Functions { /** - * ODD + * ODD * - * Returns number rounded up to the nearest odd integer. + * Returns number rounded up to the nearest odd integer. * - * @param float $number Number to round - * @return int Rounded Number + * @param float $number Number to round + * @return int Rounded Number */ public static function ODD($number) { $number = self::flattenSingleValue($number); @@ -2728,13 +2849,13 @@ class PHPExcel_Calculation_Functions { /** - * ROUNDUP + * ROUNDUP * - * Rounds a number up to a specified number of decimal places + * Rounds a number up to a specified number of decimal places * - * @param float $number Number to round - * @param int $digits Number of digits to which you want to round $number - * @return float Rounded Number + * @param float $number Number to round + * @param int $digits Number of digits to which you want to round $number + * @return float Rounded Number */ public static function ROUNDUP($number,$digits) { $number = self::flattenSingleValue($number); @@ -2753,13 +2874,13 @@ class PHPExcel_Calculation_Functions { /** - * ROUNDDOWN + * ROUNDDOWN * - * Rounds a number down to a specified number of decimal places + * Rounds a number down to a specified number of decimal places * - * @param float $number Number to round - * @param int $digits Number of digits to which you want to round $number - * @return float Rounded Number + * @param float $number Number to round + * @param int $digits Number of digits to which you want to round $number + * @return float Rounded Number */ public static function ROUNDDOWN($number,$digits) { $number = self::flattenSingleValue($number); @@ -2778,13 +2899,13 @@ class PHPExcel_Calculation_Functions { /** - * MROUND + * MROUND * - * Rounds a number to the nearest multiple of a specified value + * Rounds a number to the nearest multiple of a specified value * - * @param float $number Number to round - * @param int $multiple Multiple to which you want to round $number - * @return float Rounded Number + * @param float $number Number to round + * @param int $multiple Multiple to which you want to round $number + * @return float Rounded Number */ public static function MROUND($number,$multiple) { $number = self::flattenSingleValue($number); @@ -2805,13 +2926,13 @@ class PHPExcel_Calculation_Functions { /** - * SIGN + * SIGN * - * Determines the sign of a number. Returns 1 if the number is positive, zero (0) - * if the number is 0, and -1 if the number is negative. + * Determines the sign of a number. Returns 1 if the number is positive, zero (0) + * if the number is 0, and -1 if the number is negative. * - * @param float $number Number to round - * @return int sign value + * @param float $number Number to round + * @return int sign value */ public static function SIGN($number) { $number = self::flattenSingleValue($number); @@ -2827,13 +2948,13 @@ class PHPExcel_Calculation_Functions { /** - * FLOOR + * FLOOR * - * Rounds number down, toward zero, to the nearest multiple of significance. + * Rounds number down, toward zero, to the nearest multiple of significance. * - * @param float $number Number to round - * @param float $significance Significance - * @return float Rounded Number + * @param float $number Number to round + * @param float $significance Significance + * @return float Rounded Number */ public static function FLOOR($number,$significance=null) { $number = self::flattenSingleValue($number); @@ -2875,6 +2996,7 @@ class PHPExcel_Calculation_Functions { $numInSet = self::flattenSingleValue($numInSet); if ((is_numeric($numObjs)) && (is_numeric($numInSet))) { + $numInSet = floor($numInSet); if ($numObjs < $numInSet) { return self::$_errorCodes['num']; } @@ -2911,21 +3033,21 @@ class PHPExcel_Calculation_Functions { /** - * SERIESSUM + * SERIESSUM * - * Returns the sum of a power series + * Returns the sum of a power series * - * @param float $x Input value to the power series - * @param float $n Initial power to which you want to raise $x - * @param float $m Step by which to increase $n for each term in the series - * @param array of mixed Data Series - * @return float + * @param float $x Input value to the power series + * @param float $n Initial power to which you want to raise $x + * @param float $m Step by which to increase $n for each term in the series + * @param array of mixed Data Series + * @return float */ public static function SERIESSUM() { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); $x = array_shift($aArgs); @@ -2951,14 +3073,14 @@ class PHPExcel_Calculation_Functions { /** - * STANDARDIZE + * STANDARDIZE * - * Returns a normalized value from a distribution characterized by mean and standard_dev. + * Returns a normalized value from a distribution characterized by mean and standard_dev. * - * @param float $value Value to normalize - * @param float $mean Mean Value - * @param float $stdDev Standard Deviation - * @return float Standardized value + * @param float $value Value to normalize + * @param float $mean Mean Value + * @param float $stdDev Standard Deviation + * @return float Standardized value */ public static function STANDARDIZE($value,$mean,$stdDev) { $value = self::flattenSingleValue($value); @@ -3001,12 +3123,12 @@ class PHPExcel_Calculation_Functions { /** - * LCM + * LCM * - * Returns the lowest common multiplier of a series of numbers + * Returns the lowest common multiplier of a series of numbers * - * @param $array Values to calculate the Lowest Common Multiplier - * @return int Lowest Common Multiplier + * @param $array Values to calculate the Lowest Common Multiplier + * @return int Lowest Common Multiplier */ public static function LCM() { $aArgs = self::flattenArray(func_get_args()); @@ -3046,12 +3168,12 @@ class PHPExcel_Calculation_Functions { /** - * GCD + * GCD * - * Returns the greatest common divisor of a series of numbers + * Returns the greatest common divisor of a series of numbers * - * @param $array Values to calculate the Greatest Common Divisor - * @return int Greatest Common Divisor + * @param $array Values to calculate the Greatest Common Divisor + * @return int Greatest Common Divisor */ public static function GCD() { $aArgs = self::flattenArray(func_get_args()); @@ -3108,21 +3230,21 @@ class PHPExcel_Calculation_Functions { /** - * BINOMDIST + * BINOMDIST * - * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with - * a fixed number of tests or trials, when the outcomes of any trial are only success or failure, - * when trials are independent, and when the probability of success is constant throughout the - * experiment. For example, BINOMDIST can calculate the probability that two of the next three - * babies born are male. + * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with + * a fixed number of tests or trials, when the outcomes of any trial are only success or failure, + * when trials are independent, and when the probability of success is constant throughout the + * experiment. For example, BINOMDIST can calculate the probability that two of the next three + * babies born are male. * - * @param float $value Number of successes in trials - * @param float $trials Number of trials - * @param float $probability Probability of success on each trial - * @param boolean $cumulative - * @return float + * @param float $value Number of successes in trials + * @param float $trials Number of trials + * @param float $probability Probability of success on each trial + * @param boolean $cumulative + * @return float * - * @todo Cumulative distribution function + * @todo Cumulative distribution function * */ public static function BINOMDIST($value, $trials, $probability, $cumulative) { @@ -3154,18 +3276,18 @@ class PHPExcel_Calculation_Functions { /** - * NEGBINOMDIST + * NEGBINOMDIST * - * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that - * there will be number_f failures before the number_s-th success, when the constant - * probability of a success is probability_s. This function is similar to the binomial - * distribution, except that the number of successes is fixed, and the number of trials is - * variable. Like the binomial, trials are assumed to be independent. + * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that + * there will be number_f failures before the number_s-th success, when the constant + * probability of a success is probability_s. This function is similar to the binomial + * distribution, except that the number of successes is fixed, and the number of trials is + * variable. Like the binomial, trials are assumed to be independent. * - * @param float $failures Number of Failures - * @param float $successes Threshold number of Successes - * @param float $probability Probability of success on each trial - * @return float + * @param float $failures Number of Failures + * @param float $successes Threshold number of Successes + * @param float $probability Probability of success on each trial + * @return float * */ public static function NEGBINOMDIST($failures, $successes, $probability) { @@ -3192,17 +3314,17 @@ class PHPExcel_Calculation_Functions { /** - * CRITBINOM + * CRITBINOM * - * Returns the smallest value for which the cumulative binomial distribution is greater - * than or equal to a criterion value + * Returns the smallest value for which the cumulative binomial distribution is greater + * than or equal to a criterion value * - * See http://support.microsoft.com/kb/828117/ for details of the algorithm used + * See http://support.microsoft.com/kb/828117/ for details of the algorithm used * - * @param float $trials number of Bernoulli trials - * @param float $probability probability of a success on each trial - * @param float $alpha criterion value - * @return int + * @param float $trials number of Bernoulli trials + * @param float $probability probability of a success on each trial + * @param float $alpha criterion value + * @return int * * @todo Warning. This implementation differs from the algorithm detailed on the MS * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess @@ -3226,7 +3348,7 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } if ($alpha <= 0.5) { - $t = sqrt(log(1 / pow($alpha,2))); + $t = sqrt(log(1 / ($alpha * $alpha))); $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t)); } else { $t = sqrt(log(1 / pow(1 - $alpha,2))); @@ -3302,13 +3424,13 @@ class PHPExcel_Calculation_Functions { /** - * CHIDIST + * CHIDIST * - * Returns the one-tailed probability of the chi-squared distribution. + * Returns the one-tailed probability of the chi-squared distribution. * - * @param float $value Value for the function - * @param float $degrees degrees of freedom - * @return float + * @param float $value Value for the function + * @param float $degrees degrees of freedom + * @return float */ public static function CHIDIST($value, $degrees) { $value = self::flattenSingleValue($value); @@ -3331,22 +3453,22 @@ class PHPExcel_Calculation_Functions { /** - * CHIINV + * CHIINV * - * Returns the one-tailed probability of the chi-squared distribution. + * Returns the one-tailed probability of the chi-squared distribution. * - * @param float $probability Probability for the function - * @param float $degrees degrees of freedom - * @return float + * @param float $probability Probability for the function + * @param float $degrees degrees of freedom + * @return float */ public static function CHIINV($probability, $degrees) { $probability = self::flattenSingleValue($probability); $degrees = floor(self::flattenSingleValue($degrees)); if ((is_numeric($probability)) && (is_numeric($degrees))) { + $xLo = 100; $xHi = 0; - $maxIteration = 100; $x = $xNew = 1; $dx = 1; @@ -3387,16 +3509,16 @@ class PHPExcel_Calculation_Functions { /** - * EXPONDIST + * EXPONDIST * - * Returns the exponential distribution. Use EXPONDIST to model the time between events, - * such as how long an automated bank teller takes to deliver cash. For example, you can - * use EXPONDIST to determine the probability that the process takes at most 1 minute. + * Returns the exponential distribution. Use EXPONDIST to model the time between events, + * such as how long an automated bank teller takes to deliver cash. For example, you can + * use EXPONDIST to determine the probability that the process takes at most 1 minute. * - * @param float $value Value of the function - * @param float $lambda The parameter value - * @param boolean $cumulative - * @return float + * @param float $value Value of the function + * @param float $lambda The parameter value + * @param boolean $cumulative + * @return float */ public static function EXPONDIST($value, $lambda, $cumulative) { $value = self::flattenSingleValue($value); @@ -3420,14 +3542,14 @@ class PHPExcel_Calculation_Functions { /** - * FISHER + * FISHER * - * Returns the Fisher transformation at x. This transformation produces a function that - * is normally distributed rather than skewed. Use this function to perform hypothesis - * testing on the correlation coefficient. + * Returns the Fisher transformation at x. This transformation produces a function that + * is normally distributed rather than skewed. Use this function to perform hypothesis + * testing on the correlation coefficient. * - * @param float $value - * @return float + * @param float $value + * @return float */ public static function FISHER($value) { $value = self::flattenSingleValue($value); @@ -3443,14 +3565,14 @@ class PHPExcel_Calculation_Functions { /** - * FISHERINV + * FISHERINV * - * Returns the inverse of the Fisher transformation. Use this transformation when - * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then - * FISHERINV(y) = x. + * Returns the inverse of the Fisher transformation. Use this transformation when + * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then + * FISHERINV(y) = x. * - * @param float $value - * @return float + * @param float $value + * @return float */ public static function FISHERINV($value) { $value = self::flattenSingleValue($value); @@ -3468,11 +3590,11 @@ class PHPExcel_Calculation_Functions { private static $_logBetaCache_result = 0.0; /** - * The natural logarithm of the beta function. - * @param p require p>0 - * @param q require q>0 - * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow - * @author Jaco van Kooten + * The natural logarithm of the beta function. + * @param p require p>0 + * @param q require q>0 + * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow + * @author Jaco van Kooten */ private static function _logBeta($p, $q) { if ($p != self::$_logBetaCache_p || $q != self::$_logBetaCache_q) { @@ -3489,9 +3611,9 @@ class PHPExcel_Calculation_Functions { /** - * Evaluates of continued fraction part of incomplete beta function. - * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). - * @author Jaco van Kooten + * Evaluates of continued fraction part of incomplete beta function. + * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). + * @author Jaco van Kooten */ private static function _betaFraction($x, $p, $q) { $c = 1.0; @@ -3859,7 +3981,6 @@ class PHPExcel_Calculation_Functions { } $a = 0; $b = 2; - $maxIteration = 100; $i = 0; while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) { @@ -3922,7 +4043,7 @@ class PHPExcel_Calculation_Functions { for ($j=1;$j<=6;++$j) { $summer += ($p[$j] / ++$y); } - return exp(0 - $tmp + log(2.5066282746310005 * $summer / $x)); + return exp(0 - $tmp + log(SQRT2PI * $summer / $x)); } // function _gamma() @@ -3967,7 +4088,6 @@ class PHPExcel_Calculation_Functions { * @param float $probability Probability at which you want to evaluate the distribution * @param float $alpha Parameter to the distribution * @param float $beta Parameter to the distribution - * @param boolean $cumulative * @return float * */ @@ -3975,41 +4095,38 @@ class PHPExcel_Calculation_Functions { $probability = self::flattenSingleValue($probability); $alpha = self::flattenSingleValue($alpha); $beta = self::flattenSingleValue($beta); -// $rMin = self::flattenSingleValue($rMin); -// $rMax = self::flattenSingleValue($rMax); if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) { - if (($alpha <= 0) || ($beta <= 0) || ($probability <= 0) || ($probability > 1)) { + if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) { return self::$_errorCodes['num']; } + $xLo = 0; - $xHi = 100; - $maxIteration = 100; + $xHi = $alpha * $beta * 5; $x = $xNew = 1; - $dx = 1; + $error = $pdf = 0; + $dx = 1024; $i = 0; while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { // Apply Newton-Raphson step - $result = self::GAMMADIST($x, $alpha, $beta, True); - $error = $result - $probability; - if ($error == 0.0) { - $dx = 0; - } elseif ($error < 0.0) { + $error = self::GAMMADIST($x, $alpha, $beta, True) - $probability; + if ($error < 0.0) { $xLo = $x; } else { $xHi = $x; } + $pdf = self::GAMMADIST($x, $alpha, $beta, False); // Avoid division by zero - if ($result != 0.0) { - $dx = $error / $result; + if ($pdf != 0.0) { + $dx = $error / $pdf; $xNew = $x - $dx; } // If the NR fails to converge (which for example may be the // case if the initial guess is too rough) we apply a bisection // step to determine a more narrow interval around the root. - if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { + if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) { $xNew = ($xLo + $xHi) / 2; $dx = $xNew - $x; } @@ -4018,7 +4135,7 @@ class PHPExcel_Calculation_Functions { if ($i == MAX_ITERATIONS) { return self::$_errorCodes['na']; } - return round($x,12); + return $x; } return self::$_errorCodes['value']; } // function GAMMAINV() @@ -4072,7 +4189,7 @@ class PHPExcel_Calculation_Functions { if ($cumulative) { return 0.5 * (1 + self::_erfVal(($value - $mean) / ($stdDev * sqrt(2)))); } else { - return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean,2) / (2 * pow($stdDev,2)))); + return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean,2) / (2 * ($stdDev * $stdDev)))); } } } @@ -4224,7 +4341,7 @@ class PHPExcel_Calculation_Functions { $y = $prob - 0.5; if (abs($y) < 0.42) { - $z = pow($y,2); + $z = ($y * $y); $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1); } else { if ($y > 0) { @@ -4475,8 +4592,6 @@ class PHPExcel_Calculation_Functions { // Laboratory as reported in (among other places) "Applied Statistics // Algorithms", editied by P Griffiths and I D Hill (1985; Ellis // Horwood Ltd.; W. Sussex, England). -// $ta = 2 / pi(); - $ta = 0.636619772367581; $tterm = $degrees; $ttheta = atan2($value,sqrt($tterm)); $tc = cos($ttheta); @@ -4498,7 +4613,7 @@ class PHPExcel_Calculation_Functions { $ti += 2; } $tsum *= $ts; - if (($degrees % 2) == 1) { $tsum = $ta * ($tsum + $ttheta); } + if (($degrees % 2) == 1) { $tsum = M_2DIVPI * ($tsum + $ttheta); } $tValue = 0.5 * (1 + $tsum); if ($tails == 1) { return 1 - abs($tValue); @@ -4526,7 +4641,6 @@ class PHPExcel_Calculation_Functions { if ((is_numeric($probability)) && (is_numeric($degrees))) { $xLo = 100; $xHi = 0; - $maxIteration = 100; $x = $xNew = 1; $dx = 1; @@ -4666,6 +4780,33 @@ class PHPExcel_Calculation_Functions { } // function WEIBULL() + /** + * ZTEST + * + * Returns the Weibull distribution. Use this distribution in reliability + * analysis, such as calculating a device's mean time to failure. + * + * @param float $value + * @param float $alpha Alpha Parameter + * @param float $beta Beta Parameter + * @param boolean $cumulative + * @return float + * + */ + public static function ZTEST($dataSet, $m0, $sigma=null) { + $dataSet = self::flattenArrayIndexed($dataSet); + $m0 = self::flattenSingleValue($m0); + $sigma = self::flattenSingleValue($sigma); + + if (is_null($sigma)) { + $sigma = self::STDEV($dataSet); + } + $n = count($dataSet); + + return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0)/($sigma/SQRT($n))); + } // function ZTEST() + + /** * SKEW * @@ -4678,17 +4819,21 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function SKEW() { - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $mean = self::AVERAGE($aArgs); $stdDev = self::STDEV($aArgs); $count = $summer = 0; // Loop through arguments - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summer += pow((($arg - $mean) / $stdDev),3) ; - ++$count; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summer += pow((($arg - $mean) / $stdDev),3) ; + ++$count; + } } } @@ -4712,18 +4857,22 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function KURT() { - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $mean = self::AVERAGE($aArgs); $stdDev = self::STDEV($aArgs); if ($stdDev > 0) { $count = $summer = 0; // Loop through arguments - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summer += pow((($arg - $mean) / $stdDev),4) ; - ++$count; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summer += pow((($arg - $mean) / $stdDev),4) ; + ++$count; + } } } @@ -4766,6 +4915,14 @@ class PHPExcel_Calculation_Functions { $a = self::flattenSingleValue($a); $b = self::flattenSingleValue($b); + if ($b == 0.0) { + return self::$_errorCodes['divisionbyzero']; + } elseif (($a < 0.0) && ($b > 0.0)) { + return $b - fmod(abs($a),$b); + } elseif (($a > 0.0) && ($b < 0.0)) { + return $b + fmod($a,abs($b)); + } + return fmod($a,$b); } // function MOD() @@ -4779,6 +4936,10 @@ class PHPExcel_Calculation_Functions { public static function CHARACTER($character) { $character = self::flattenSingleValue($character); + if ((!is_numeric($character)) || ($character < 0)) { + return self::$_errorCodes['value']; + } + if (function_exists('mb_convert_encoding')) { return mb_convert_encoding('&#'.intval($character).';', 'UTF-8', 'HTML-ENTITIES'); } else { @@ -4786,6 +4947,25 @@ class PHPExcel_Calculation_Functions { } } + + private static function _uniord($c) { + if (ord($c{0}) >=0 && ord($c{0}) <= 127) + return ord($c{0}); + if (ord($c{0}) >= 192 && ord($c{0}) <= 223) + return (ord($c{0})-192)*64 + (ord($c{1})-128); + if (ord($c{0}) >= 224 && ord($c{0}) <= 239) + return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); + if (ord($c{0}) >= 240 && ord($c{0}) <= 247) + return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); + if (ord($c{0}) >= 248 && ord($c{0}) <= 251) + return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); + if (ord($c{0}) >= 252 && ord($c{0}) <= 253) + return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); + if (ord($c{0}) >= 254 && ord($c{0}) <= 255) //error + return self::$_errorCodes['value']; + return 0; + } // function _uniord() + /** * ASCIICODE * @@ -4806,22 +4986,14 @@ class PHPExcel_Calculation_Functions { } } + $character = $characters; if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { - if (mb_strlen($characters, 'UTF-8') > 0) { - $character = mb_substr($characters, 0, 1, 'UTF-8'); - $byteLength = strlen($character); - $xValue = 0; - for ($i = 0; $i < $byteLength; ++$i) { - $xValue = ($xValue * 256) + ord($character{$i}); - } - return $xValue; - } + if (mb_strlen($characters, 'UTF-8') > 1) { $character = mb_substr($characters, 0, 1, 'UTF-8'); } + return self::_uniord($character); } else { - if (strlen($characters) > 0) { - return ord(substr($characters, 0, 1)); - } + if (strlen($characters) > 0) { $character = substr($characters, 0, 1); } + return ord($character); } - return self::$_errorCodes['value']; } // function ASCIICODE() @@ -4834,7 +5006,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = ''; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { if (is_bool($arg)) { @@ -4866,6 +5038,10 @@ class PHPExcel_Calculation_Functions { public static function STRINGLENGTH($value = '') { $value = self::flattenSingleValue($value); + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_strlen')) { return mb_strlen($value, 'UTF-8'); } else { @@ -4883,18 +5059,24 @@ class PHPExcel_Calculation_Functions { * @return string */ public static function SEARCHSENSITIVE($needle,$haystack,$offset=1) { - $needle = (string) self::flattenSingleValue($needle); - $haystack = (string) self::flattenSingleValue($haystack); + $needle = self::flattenSingleValue($needle); + $haystack = self::flattenSingleValue($haystack); $offset = self::flattenSingleValue($offset); - if (($offset > 0) && (strlen($haystack) > $offset)) { - if (function_exists('mb_strpos')) { - $pos = mb_strpos($haystack, $needle, --$offset,'UTF-8'); - } else { - $pos = strpos($haystack, $needle, --$offset); + if (!is_bool($needle)) { + if (is_bool($haystack)) { + $haystack = ($haystack) ? 'TRUE' : 'FALSE'; } - if ($pos !== false) { - return ++$pos; + + if (($offset > 0) && (strlen($haystack) > $offset)) { + if (function_exists('mb_strpos')) { + $pos = mb_strpos($haystack, $needle, --$offset,'UTF-8'); + } else { + $pos = strpos($haystack, $needle, --$offset); + } + if ($pos !== false) { + return ++$pos; + } } } return self::$_errorCodes['value']; @@ -4910,18 +5092,24 @@ class PHPExcel_Calculation_Functions { * @return string */ public static function SEARCHINSENSITIVE($needle,$haystack,$offset=1) { - $needle = (string) self::flattenSingleValue($needle); - $haystack = (string) self::flattenSingleValue($haystack); + $needle = self::flattenSingleValue($needle); + $haystack = self::flattenSingleValue($haystack); $offset = self::flattenSingleValue($offset); - if (($offset > 0) && (strlen($haystack) > $offset)) { - if (function_exists('mb_stripos')) { - $pos = mb_stripos($haystack, $needle, --$offset,'UTF-8'); - } else { - $pos = stripos($haystack, $needle, --$offset); + if (!is_bool($needle)) { + if (is_bool($haystack)) { + $haystack = ($haystack) ? 'TRUE' : 'FALSE'; } - if ($pos !== false) { - return ++$pos; + + if (($offset > 0) && (strlen($haystack) > $offset)) { + if (function_exists('mb_stripos')) { + $pos = mb_stripos($haystack, $needle, --$offset,'UTF-8'); + } else { + $pos = stripos($haystack, $needle, --$offset); + } + if ($pos !== false) { + return ++$pos; + } } } return self::$_errorCodes['value']; @@ -4939,6 +5127,14 @@ class PHPExcel_Calculation_Functions { $value = self::flattenSingleValue($value); $chars = self::flattenSingleValue($chars); + if ($chars < 0) { + return self::$_errorCodes['value']; + } + + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_substr')) { return mb_substr($value, 0, $chars, 'UTF-8'); } else { @@ -4958,6 +5154,14 @@ class PHPExcel_Calculation_Functions { $value = self::flattenSingleValue($value); $chars = self::flattenSingleValue($chars); + if ($chars < 0) { + return self::$_errorCodes['value']; + } + + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); } else { @@ -4979,6 +5183,14 @@ class PHPExcel_Calculation_Functions { $start = self::flattenSingleValue($start); $chars = self::flattenSingleValue($chars); + if (($start < 1) || ($chars < 0)) { + return self::$_errorCodes['value']; + } + + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_substr')) { return mb_substr($value, --$start, $chars, 'UTF-8'); } else { @@ -5008,6 +5220,53 @@ class PHPExcel_Calculation_Functions { } // function REPLACE() + /** + * SUBSTITUTE + * + * @param string $text Value + * @param string $fromText From Value + * @param string $toText To Value + * @param integer $instance Instance Number + * @return string + */ + public static function SUBSTITUTE($text = '', $fromText = '', $toText = '', $instance = 0) { + $text = self::flattenSingleValue($text); + $fromText = self::flattenSingleValue($fromText); + $toText = self::flattenSingleValue($toText); + $instance = floor(self::flattenSingleValue($instance)); + + if ($instance == 0) { + if(function_exists('mb_str_replace')) { + return mb_str_replace($fromText,$toText,$text); + } else { + return str_replace($fromText,$toText,$text); + } + } else { + $pos = -1; + while($instance > 0) { + if (function_exists('mb_strpos')) { + $pos = mb_strpos($text, $fromText, $pos+1, 'UTF-8'); + } else { + $pos = strpos($text, $fromText, $pos+1); + } + if ($pos === false) { + break; + } + --$instance; + } + if ($pos !== false) { + if (function_exists('mb_strlen')) { + return self::REPLACE($text,++$pos,mb_strlen($fromText, 'UTF-8'),$toText); + } else { + return self::REPLACE($text,++$pos,strlen($fromText),$toText); + } + } + } + + return $left.$newText.$right; + } // function SUBSTITUTE() + + /** * RETURNSTRING * @@ -5055,6 +5314,10 @@ class PHPExcel_Calculation_Functions { $value = self::flattenSingleValue($value); $format = self::flattenSingleValue($format); + if ((is_string($value)) && (!is_numeric($value)) && PHPExcel_Shared_Date::isDateTimeFormatCode($format)) { + $value = self::DATEVALUE($value); + } + return (string) PHPExcel_Style_NumberFormat::toFormattedString($value,$format); } // function TEXTFORMAT() @@ -5086,6 +5349,10 @@ class PHPExcel_Calculation_Functions { public static function TRIMNONPRINTABLE($stringValue = '') { $stringValue = self::flattenSingleValue($stringValue); + if (is_bool($stringValue)) { + $stringValue = ($stringValue) ? 'TRUE' : 'FALSE'; + } + if (self::$_invalidChars == Null) { self::$_invalidChars = range(chr(0),chr(31)); } @@ -5123,7 +5390,7 @@ class PHPExcel_Calculation_Functions { * @param mixed $value Value to check * @return boolean */ - public static function IS_BLANK($value = null) { + public static function IS_BLANK($value=null) { if (!is_null($value)) { $value = self::flattenSingleValue($value); } @@ -5262,7 +5529,7 @@ class PHPExcel_Calculation_Functions { * @return string Version information */ public static function VERSION() { - return 'PHPExcel 1.7.0, 2009-08-10'; + return 'PHPExcel 1.7.2, 2010-01-11'; } // function VERSION() @@ -5408,7 +5675,7 @@ class PHPExcel_Calculation_Functions { * depending on the value of the ReturnDateType flag */ public static function DATEVALUE($dateValue = 1) { - $dateValue = str_replace(array('/','.',' '),array('-','-','-'),self::flattenSingleValue(trim($dateValue,'"'))); + $dateValue = str_replace(array('/','.',' '),array('-','-','-'),trim(self::flattenSingleValue($dateValue),'"')); $yearFound = false; $t1 = explode('-',$dateValue); @@ -5723,7 +5990,8 @@ class PHPExcel_Calculation_Functions { } break; case 'YM': - $retVal = abs(intval($endMonths - $startMonths)); + $retVal = intval($endMonths - $startMonths); + if ($retVal < 0) $retVal = 12 + $retVal; // We're only interested in full months if ($endDays < $startDays) { --$retVal; @@ -5736,7 +6004,8 @@ class PHPExcel_Calculation_Functions { $PHPEndDateObject->modify('-1 year'); $endYears = $PHPEndDateObject->format('Y'); } - $retVal = abs($PHPEndDateObject->format('z') - $PHPStartDateObject->format('z')); + $retVal = $PHPEndDateObject->format('z') - $PHPStartDateObject->format('z'); + if ($retVal < 0) { $retVal += 365; } } break; } @@ -5959,10 +6228,14 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue == 0.0) { + return 0; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function - $PHPDateObject = &PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); return (int) $PHPDateObject->format('j'); } // function DAYOFMONTH() @@ -5980,6 +6253,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6031,6 +6306,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6058,6 +6335,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6078,6 +6357,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6109,15 +6390,14 @@ class PHPExcel_Calculation_Functions { } } // Execute function - if (is_real($timeValue)) { - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return self::$_errorCodes['num']; } - return (int) date('G',$timeValue); + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('G',$timeValue); } // function HOUROFDAY() @@ -6143,15 +6423,14 @@ class PHPExcel_Calculation_Functions { } } // Execute function - if (is_real($timeValue)) { - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return self::$_errorCodes['num']; } - return (int) date('i',$timeValue); + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('i',$timeValue); } // function MINUTEOFHOUR() @@ -6177,15 +6456,14 @@ class PHPExcel_Calculation_Functions { } } // Execute function - if (is_real($timeValue)) { - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return self::$_errorCodes['num']; } - return (int) date('s',$timeValue); + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('s',$timeValue); } // function SECONDOFMINUTE() @@ -6664,9 +6942,9 @@ class PHPExcel_Calculation_Functions { if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { return self::$_errorCodes['num']; } - $binVal = decbin(octdec($x)); + $r = decbin(octdec($x)); - return self::_nbrConversionFormat($binVal,$places); + return self::_nbrConversionFormat($r,$places); } // function OCTTOBIN() @@ -6892,16 +7170,16 @@ class PHPExcel_Calculation_Functions { if ($parsedComplex['imaginary'] == 0.0) { return 0.0; } elseif($parsedComplex['imaginary'] < 0.0) { - return pi() / -2; + return M_PI / -2; } else { - return pi() / 2; + return M_PI / 2; } } elseif ($parsedComplex['real'] > 0.0) { return atan($parsedComplex['imaginary'] / $parsedComplex['real']); } elseif ($parsedComplex['imaginary'] < 0.0) { - return 0 - (pi() - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real']))); + return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real']))); } else { - return pi() - atan($parsedComplex['imaginary'] / abs($parsedComplex['real'])); + return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real'])); } } // function IMARGUMENT() @@ -8106,7 +8384,7 @@ class PHPExcel_Calculation_Functions { $fTerm = pow($x / 2, $n) / self::FACT($n); $nK = 1; $fResult = $fTerm; - $fSqrX = pow($x,2) / 4; + $fSqrX = ($x * $x) / 4; do { $fTerm *= $fSqrX; $fTerm /= ($nK * ($nK + $n)); @@ -8142,16 +8420,15 @@ class PHPExcel_Calculation_Functions { if ($n < 0) { return self::$_errorCodes['num']; } - $f_2_DIV_PI = 2 / pi(); - $f_PI_DIV_2 = pi() / 2; - $f_PI_DIV_4 = pi() / 4; + $f_PI_DIV_2 = M_PI / 2; + $f_PI_DIV_4 = M_PI / 4; $fResult = 0; if (abs($x) <= 30) { $fTerm = pow($x / 2, $n) / self::FACT($n); $nK = 1; $fResult = $fTerm; - $fSqrX = pow($x,2) / -4; + $fSqrX = ($x * $x) / -4; do { $fTerm *= $fSqrX; $fTerm /= ($nK * ($nK + $n)); @@ -8159,7 +8436,7 @@ class PHPExcel_Calculation_Functions { } while ((abs($fTerm) > 1e-10) && (++$nK < 100)); } else { $fXAbs = abs($x); - $fResult = sqrt($f_2_DIV_PI / $fXAbs) * cos($fXAbs - $n * $f_PI_DIV_2 - $f_PI_DIV_4); + $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $n * $f_PI_DIV_2 - $f_PI_DIV_4); if (($n && 1) && ($x < 0)) { $fResult = -$fResult; } @@ -8173,7 +8450,7 @@ class PHPExcel_Calculation_Functions { private static function _Besselk0($fNum) { if ($fNum <= 2) { $fNum2 = $fNum * 0.5; - $y = pow($fNum2,2); + $y = ($fNum2 * $fNum2); $fRet = -log($fNum2) * self::BESSELI($fNum, 0) + (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y * (0.10750e-3 + $y * 0.74e-5)))))); @@ -8190,7 +8467,7 @@ class PHPExcel_Calculation_Functions { private static function _Besselk1($fNum) { if ($fNum <= 2) { $fNum2 = $fNum * 0.5; - $y = pow($fNum2,2); + $y = ($fNum2 * $fNum2); $fRet = log($fNum2) * self::BESSELI($fNum, 1) + (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y * (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum; @@ -8244,17 +8521,17 @@ class PHPExcel_Calculation_Functions { private static function _Bessely0($fNum) { if ($fNum < 8.0) { - $y = pow($fNum,2); + $y = ($fNum * $fNum); $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733)))); $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y)))); - $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum); + $fRet = $f1 / $f2 + M_2DIVPI * self::BESSELJ($fNum, 0) * log($fNum); } else { $z = 8.0 / $fNum; - $y = pow($z,2); + $y = ($z * $z); $xx = $fNum - 0.785398164; $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6))); $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7)))); - $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); + $fRet = sqrt(M_2DIVPI / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); } return $fRet; } // function _Bessely0() @@ -8262,21 +8539,21 @@ class PHPExcel_Calculation_Functions { private static function _Bessely1($fNum) { if ($fNum < 8.0) { - $y = pow($fNum,2); + $y = ($fNum * $fNum); $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y * (-0.4237922726e7 + $y * 0.8511937935e4))))); $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y * (0.1020426050e6 + $y * (0.3549632885e3 + $y))))); - $fRet = $f1 / $f2 + 0.636619772 * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); + $fRet = $f1 / $f2 + M_2DIVPI * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); } else { $z = 8.0 / $fNum; - $y = pow($z,2); + $y = ($z * $z); $xx = $fNum - 2.356194491; $f1 = 1 + $y * (0.183105e-2 + $y * (-0.3516396496e-4 + $y * (0.2457520174e-5 + $y * (-0.240337019e6)))); $f2 = 0.04687499995 + $y * (-0.2002690873e-3 + $y * (0.8449199096e-5 + $y * (-0.88228987e-6 + $y * 0.105787412e-6))); - $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); + $fRet = sqrt(M_2DIVPI / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); #i12430# ...but this seems to work much better. -// $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491); +// $fRet = sqrt(M_2DIVPI / $fNum) * sin($fNum - 2.356194491); } return $fRet; } // function _Bessely1() @@ -8358,14 +8635,13 @@ class PHPExcel_Calculation_Functions { // Private method to calculate the erf value // private static $_two_sqrtpi = 1.128379167095512574; - private static $_rel_error = 1E-15; private static function _erfVal($x) { if (abs($x) > 2.2) { return 1 - self::_erfcVal($x); } $sum = $term = $x; - $xsqr = pow($x,2); + $xsqr = ($x * $x); $j = 1; do { $term *= $xsqr / $j; @@ -8374,10 +8650,10 @@ class PHPExcel_Calculation_Functions { $term *= $xsqr / $j; $sum += $term / (2 * $j + 1); ++$j; - if ($sum == 0) { + if ($sum == 0.0) { break; } - } while (abs($term / $sum) > self::$_rel_error); + } while (abs($term / $sum) > PRECISION); return self::$_two_sqrtpi * $sum; } // function _erfVal() @@ -8428,7 +8704,7 @@ class PHPExcel_Calculation_Functions { } $a = $n = 1; $b = $c = $x; - $d = pow($x,2) + 0.5; + $d = ($x * $x) + 0.5; $q1 = $q2 = $b / $d; $t = 0; do { @@ -8441,7 +8717,7 @@ class PHPExcel_Calculation_Functions { $n += 0.5; $q1 = $q2; $q2 = $b / $d; - } while ((abs($q1 - $q2) / $q2) > self::$_rel_error); + } while ((abs($q1 - $q2) / $q2) > PRECISION); return self::$_one_sqrtpi * exp(-$x * $x) * $q2; } // function _erfcVal() @@ -8478,6 +8754,10 @@ class PHPExcel_Calculation_Functions { public static function LOWERCASE($mixedCaseString) { $mixedCaseString = self::flattenSingleValue($mixedCaseString); + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_convert_case')) { return mb_convert_case($mixedCaseString, MB_CASE_LOWER, 'UTF-8'); } else { @@ -8497,6 +8777,10 @@ class PHPExcel_Calculation_Functions { public static function UPPERCASE($mixedCaseString) { $mixedCaseString = self::flattenSingleValue($mixedCaseString); + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_convert_case')) { return mb_convert_case($mixedCaseString, MB_CASE_UPPER, 'UTF-8'); } else { @@ -8516,6 +8800,10 @@ class PHPExcel_Calculation_Functions { public static function PROPERCASE($mixedCaseString) { $mixedCaseString = self::flattenSingleValue($mixedCaseString); + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_convert_case')) { return mb_convert_case($mixedCaseString, MB_CASE_TITLE, 'UTF-8'); } else { @@ -8538,7 +8826,7 @@ class PHPExcel_Calculation_Functions { */ public static function DOLLAR($value = 0, $decimals = 2) { $value = self::flattenSingleValue($value); - $decimals = self::flattenSingleValue($decimals); + $decimals = is_null($decimals) ? 0 : self::flattenSingleValue($decimals); // Validate parameters if (!is_numeric($value) || !is_numeric($decimals)) { @@ -8730,6 +9018,22 @@ class PHPExcel_Calculation_Functions { } // function FV() + /** + * FVSCHEDULE + * + */ + public static function FVSCHEDULE($principal, $schedule) { + $principal = self::flattenSingleValue($principal); + $schedule = self::flattenArray($schedule); + + foreach($schedule as $n) { + $principal *= 1 + $n; + } + + return $principal; + } // function FVSCHEDULE() + + /** * PMT * @@ -8802,6 +9106,7 @@ class PHPExcel_Calculation_Functions { } // function NPER() + private static function _interestAndPrincipal($rate=0, $per=0, $nper=0, $pv=0, $fv=0, $type=0) { $pmt = self::PMT($rate, $nper, $pv, $fv, $type); $capital = $pv; @@ -8964,6 +9269,47 @@ class PHPExcel_Calculation_Functions { } // function CUMPRINC() + /** + * ISPMT + * + * Returns the interest payment for an investment based on an interest rate and a constant payment schedule. + * + * Excel Function: + * =ISPMT(interest_rate, period, number_payments, PV) + * + * interest_rate is the interest rate for the investment + * + * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments. + * + * number_payments is the number of payments for the annuity + * + * PV is the loan amount or present value of the payments + */ + public static function ISPMT() { + // Return value + $returnValue = 0; + + // Get the parameters + $aArgs = self::flattenArray(func_get_args()); + $interestRate = array_shift($aArgs); + $period = array_shift($aArgs); + $numberPeriods = array_shift($aArgs); + $principleRemaining = array_shift($aArgs); + + // Calculate + $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0); + for($i=0; $i <= $period; ++$i) { + $returnValue = $interestRate * $principleRemaining * -1; + $principleRemaining -= $principlePayment; + // principle needs to be 0 after the last payment, don't let floating point screw it up + if($i == $numberPeriods) { + $returnValue = 0; + } + } + return($returnValue); + } // function ISPMT() + + /** * NPV * @@ -8977,7 +9323,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); // Calculate @@ -8994,6 +9340,188 @@ class PHPExcel_Calculation_Functions { } // function NPV() + /** + * XNPV + * + * Returns the net present value for a schedule of cash flows that is not necessarily periodic. + * To calculate the net present value for a series of cash flows that is periodic, use the NPV function. + * + * @param float Discount interest rate + * @param array Cash flow series + * @return float + */ + public static function XNPV($rate, $values, $dates) { + if ((!is_array($values)) || (!is_array($dates))) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $dates = self::flattenArray($dates); + $valCount = count($values); + if ($valCount != count($dates)) return self::$_errorCodes['num']; + + $xnpv = 0.0; + for ($i = 0; $i < $valCount; ++$i) { + $xnpv += $values[$i] / pow(1 + $rate, self::DATEDIF($dates[0],$dates[$i],'d') / 365); + } + return (is_finite($xnpv) ? $xnpv : self::$_errorCodes['value']); + } // function XNPV() + + + public static function IRR($values, $guess = 0.1) { + if (!is_array($values)) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $guess = self::flattenSingleValue($guess); + + // create an initial range, with a root somewhere between 0 and guess + $x1 = 0.0; + $x2 = $guess; + $f1 = self::NPV($x1, $values); + $f2 = self::NPV($x2, $values); + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + if (($f1 * $f2) < 0.0) break; + if (abs($f1) < abs($f2)) { + $f1 = self::NPV($x1 += 1.6 * ($x1 - $x2), $values); + } else { + $f2 = self::NPV($x2 += 1.6 * ($x2 - $x1), $values); + } + } + if (($f1 * $f2) > 0.0) return self::$_errorCodes['value']; + + $f = self::NPV($x1, $values); + if ($f < 0.0) { + $rtb = $x1; + $dx = $x2 - $x1; + } else { + $rtb = $x2; + $dx = $x1 - $x2; + } + + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + $dx *= 0.5; + $x_mid = $rtb + $dx; + $f_mid = self::NPV($x_mid, $values); + if ($f_mid <= 0.0) $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; + } + return self::$_errorCodes['value']; + } // function IRR() + + + public static function MIRR($values, $finance_rate, $reinvestment_rate) { + if (!is_array($values)) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $finance_rate = self::flattenSingleValue($finance_rate); + $reinvestment_rate = self::flattenSingleValue($reinvestment_rate); + $n = count($values); + + $rr = 1.0 + $reinvestment_rate; + $fr = 1.0 + $finance_rate; + + $npv_pos = $npv_neg = 0.0; + foreach($values as $i => $v) { + if ($v >= 0) { + $npv_pos += $v / pow($rr, $i); + } else { + $npv_neg += $v / pow($fr, $i); + } + } + + if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= -1)) { + return self::$_errorCodes['value']; + } + + $mirr = pow((-$npv_pos * pow($rr, $n)) + / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0; + + return (is_finite($mirr) ? $mirr : self::$_errorCodes['value']); + } // function MIRR() + + + public static function XIRR($values, $dates, $guess = 0.1) { + if ((!is_array($values)) && (!is_array($dates))) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $dates = self::flattenArray($dates); + $guess = self::flattenSingleValue($guess); + if (count($values) != count($dates)) return self::$_errorCodes['num']; + + // create an initial range, with a root somewhere between 0 and guess + $x1 = 0.0; + $x2 = $guess; + $f1 = self::XNPV($x1, $values, $dates); + $f2 = self::XNPV($x2, $values, $dates); + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + if (($f1 * $f2) < 0.0) break; + if (abs($f1) < abs($f2)) { + $f1 = self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates); + } else { + $f2 = self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates); + } + } + if (($f1 * $f2) > 0.0) return self::$_errorCodes['value']; + + $f = self::XNPV($x1, $values, $dates); + if ($f < 0.0) { + $rtb = $x1; + $dx = $x2 - $x1; + } else { + $rtb = $x2; + $dx = $x1 - $x2; + } + + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + $dx *= 0.5; + $x_mid = $rtb + $dx; + $f_mid = self::XNPV($x_mid, $values, $dates); + if ($f_mid <= 0.0) $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; + } + return self::$_errorCodes['value']; + } + + + /** + * RATE + * + **/ + public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { + $nper = (int) self::flattenSingleValue($nper); + $pmt = self::flattenSingleValue($pmt); + $pv = self::flattenSingleValue($pv); + $fv = (is_null($fv)) ? 0.0 : self::flattenSingleValue($fv); + $type = (is_null($type)) ? 0 : (int) self::flattenSingleValue($type); + $guess = (is_null($guess)) ? 0.1 : self::flattenSingleValue($guess); + + $rate = $guess; + if (abs($rate) < FINANCIAL_PRECISION) { + $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; + } else { + $f = exp($nper * log(1 + $rate)); + $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + } + $y0 = $pv + $pmt * $nper + $fv; + $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + + // find root by secant method + $i = $x0 = 0.0; + $x1 = $rate; + while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) { + $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); + $x0 = $x1; + $x1 = $rate; + + if (abs($rate) < FINANCIAL_PRECISION) { + $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; + } else { + $f = exp($nper * log(1 + $rate)); + $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + } + + $y0 = $y1; + $y1 = $y; + ++$i; + } + return $rate; + } // function RATE() + + /** * DB * @@ -9039,6 +9567,9 @@ class PHPExcel_Calculation_Functions { } $previousDepreciation += $depreciation; } + if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { + $depreciation = round($depreciation,2); + } return $depreciation; } return self::$_errorCodes['value']; @@ -9080,6 +9611,9 @@ class PHPExcel_Calculation_Functions { $depreciation = min( ($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation) ); $previousDepreciation += $depreciation; } + if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { + $depreciation = round($depreciation,2); + } return $depreciation; } return self::$_errorCodes['value']; @@ -9133,9 +9667,9 @@ class PHPExcel_Calculation_Functions { $firstinter = self::flattenSingleValue($firstinter); $settlement = self::flattenSingleValue($settlement); $rate = (float) self::flattenSingleValue($rate); - $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); - $frequency = (is_null($frequency)) ? 1 : (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); + $frequency = (is_null($frequency)) ? 1 : (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); // Validate if ((is_numeric($rate)) && (is_numeric($par))) { @@ -9179,8 +9713,8 @@ class PHPExcel_Calculation_Functions { $issue = self::flattenSingleValue($issue); $settlement = self::flattenSingleValue($settlement); $rate = (float) self::flattenSingleValue($rate); - $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); // Validate if ((is_numeric($rate)) && (is_numeric($par))) { @@ -9204,13 +9738,116 @@ class PHPExcel_Calculation_Functions { public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { + $cost = self::flattenSingleValue($cost); + $purchased = self::flattenSingleValue($purchased); + $firstPeriod = self::flattenSingleValue($firstPeriod); + $salvage = self::flattenSingleValue($salvage); + $period = floor(self::flattenSingleValue($period)); + $rate = self::flattenSingleValue($rate); + $basis = floor(self::flattenSingleValue($basis)); + + $fUsePer = 1.0 / $rate; + + if ($fUsePer < 3.0) { + $amortiseCoeff = 1.0; + } elseif ($fUsePer < 5.0) { + $amortiseCoeff = 1.5; + } elseif ($fUsePer <= 6.0) { + $amortiseCoeff = 2.0; + } else { + $amortiseCoeff = 2.5; + } + + $rate *= $amortiseCoeff; + $fNRate = floor((self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost) + 0.5); + $cost -= $fNRate; + $fRest = $cost - $salvage; + + for ($n = 0; $n < $period; ++$n) { + $fNRate = floor(($rate * $cost) + 0.5); + $fRest -= $fNRate; + + if ($fRest < 0.0) { + switch ($period - $n) { + case 0 : + case 1 : return floor(($cost * 0.5) + 0.5); + break; + default : return 0.0; + break; + } + } + $cost -= $fNRate; + } + return $fNRate; } // function AMORDEGRC() public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { + $cost = self::flattenSingleValue($cost); + $purchased = self::flattenSingleValue($purchased); + $firstPeriod = self::flattenSingleValue($firstPeriod); + $salvage = self::flattenSingleValue($salvage); + $period = self::flattenSingleValue($period); + $rate = self::flattenSingleValue($rate); + $basis = self::flattenSingleValue($basis); + + $fOneRate = $cost * $rate; + $fCostDelta = $cost - $salvage; + $f0Rate = self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost; + $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate); + + if ($period == 0) { + return $f0Rate; + } elseif ($period <= $nNumOfFullPeriods) { + return $fOneRate; + } elseif ($period == ($nNumOfFullPeriods + 1)) { + return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate); + } else { + return 0.0; + } } // function AMORLINC() + public static function COUPNUM($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = self::flattenSingleValue($frequency); + $basis = self::flattenSingleValue($basis); + + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; + + switch ($frequency) { + case 1: // annual payments + return ceil($daysBetweenSettlementAndMaturity / 360); + case 2: // half-yearly + return ceil($daysBetweenSettlementAndMaturity / 180); + case 4: // quarterly + return ceil($daysBetweenSettlementAndMaturity / 90); + } + return self::$_errorCodes['value']; + } // function COUPNUM() + + + public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = self::flattenSingleValue($frequency); + $basis = self::flattenSingleValue($basis); + + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; + + switch ($frequency) { + case 1: // annual payments + return 365 - ($daysBetweenSettlementAndMaturity % 360); + case 2: // half-yearly + return 365 - ($daysBetweenSettlementAndMaturity % 360); + case 4: // quarterly + return self::DATEDIF($maturity, $settlement); + } + return self::$_errorCodes['value']; + } // function COUPDAYBS() + + /** * DISC * @@ -9466,12 +10103,15 @@ class PHPExcel_Calculation_Functions { if (is_string($maturity = self::_getDateValue($maturity))) { return self::$_errorCodes['value']; } - ++$maturity; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity); - $daysBetweenSettlementAndMaturity *= 360; + if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; + } else { + $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); + } - return (365 * $discount) / (360 - ($discount * ($daysBetweenSettlementAndMaturity))); + return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity); } // function TBILLEQ() @@ -9495,7 +10135,6 @@ class PHPExcel_Calculation_Functions { if (is_string($maturity = self::_getDateValue($maturity))) { return self::$_errorCodes['value']; } - ++$maturity; // Validate if (is_numeric($discount)) { @@ -9503,11 +10142,16 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; + if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + return $daysBetweenSettlementAndMaturity; + } + } else { + $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); } - $daysBetweenSettlementAndMaturity *= 360; + if ($daysBetweenSettlementAndMaturity > 360) { return self::$_errorCodes['num']; } @@ -9545,14 +10189,16 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; + if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + return $daysBetweenSettlementAndMaturity; + } + } else { + $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); } - $daysBetweenSettlementAndMaturity *= 360; -// Sometimes we need to add 1, sometimes not. I haven't yet worked out the rule which determines this. - ++$daysBetweenSettlementAndMaturity; if ($daysBetweenSettlementAndMaturity > 360) { return self::$_errorCodes['num']; } @@ -9698,15 +10344,22 @@ class PHPExcel_Calculation_Functions { /** - * CELL_ADDRESS + * CELL_ADDRESS * - * Returns the straight-line depreciation of an asset for one period + * Creates a cell address as text, given specified row and column numbers. * - * @param row Row number to use in the cell reference - * @param column Column number to use in the cell reference - * @param relativity Flag indicating the type of reference to return - * @param sheetText Name of worksheet to use - * @return string + * @param row Row number to use in the cell reference + * @param column Column number to use in the cell reference + * @param relativity Flag indicating the type of reference to return + * 1 or omitted Absolute + * 2 Absolute row; relative column + * 3 Relative row; absolute column + * 4 Relative + * @param referenceStyle A logical value that specifies the A1 or R1C1 reference style. + * TRUE or omitted CELL_ADDRESS returns an A1-style reference + * FALSE CELL_ADDRESS returns an R1C1-style reference + * @param sheetText Optional Name of worksheet to use + * @return string */ public static function CELL_ADDRESS($row, $column, $relativity=1, $referenceStyle=True, $sheetText='') { $row = self::flattenSingleValue($row); @@ -9714,6 +10367,10 @@ class PHPExcel_Calculation_Functions { $relativity = self::flattenSingleValue($relativity); $sheetText = self::flattenSingleValue($sheetText); + if (($row < 1) || ($column < 1)) { + return self::$_errorCodes['value']; + } + if ($sheetText > '') { if (strpos($sheetText,' ') !== False) { $sheetText = "'".$sheetText."'"; } $sheetText .='!'; @@ -9732,85 +10389,268 @@ class PHPExcel_Calculation_Functions { } // function CELL_ADDRESS() + /** + * COLUMN + * + * Returns the column number of the given cell reference + * If the cell reference is a range of cells, COLUMN returns the column numbers of each column in the reference as a horizontal array. + * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the + * reference of the cell in which the COLUMN function appears; otherwise this function returns 0. + * + * @param cellAddress A reference to a range of cells for which you want the column numbers + * @return integer or array of integer + */ public static function COLUMN($cellAddress=Null) { - if (is_null($cellAddress) || $cellAddress === '') { - return 0; - } + if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } - foreach($cellAddress as $columnKey => $value) { - return PHPExcel_Cell::columnIndexFromString($columnKey); + if (is_array($cellAddress)) { + foreach($cellAddress as $columnKey => $value) { + $columnKey = preg_replace('/[^a-z]/i','',$columnKey); + return (integer) PHPExcel_Cell::columnIndexFromString($columnKey); + } + } else { + if (strpos($cellAddress,'!') !== false) { + list($sheet,$cellAddress) = explode('!',$cellAddress); + } + if (strpos($cellAddress,':') !== false) { + list($startAddress,$endAddress) = explode(':',$cellAddress); + $startAddress = preg_replace('/[^a-z]/i','',$startAddress); + $endAddress = preg_replace('/[^a-z]/i','',$endAddress); + $returnValue = array(); + do { + $returnValue[] = (integer) PHPExcel_Cell::columnIndexFromString($startAddress); + } while ($startAddress++ != $endAddress); + return $returnValue; + } else { + $cellAddress = preg_replace('/[^a-z]/i','',$cellAddress); + return (integer) PHPExcel_Cell::columnIndexFromString($cellAddress); + } } } // function COLUMN() - public static function ROW($cellAddress=Null) { - if ($cellAddress === Null) { - return 0; + /** + * COLUMNS + * + * Returns the number of columns in an array or reference. + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns + * @return integer + */ + public static function COLUMNS($cellAddress=Null) { + if (is_null($cellAddress) || $cellAddress === '') { + return 1; + } elseif (!is_array($cellAddress)) { + return self::$_errorCodes['value']; } - foreach($cellAddress as $columnKey => $rowValue) { - foreach($rowValue as $rowKey => $cellValue) { - return $rowKey; + $isMatrix = (is_numeric(array_shift(array_keys($cellAddress)))); + list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); + + if ($isMatrix) { + return $rows; + } else { + return $columns; + } + } // function COLUMNS() + + + /** + * ROW + * + * Returns the row number of the given cell reference + * If the cell reference is a range of cells, ROW returns the row numbers of each row in the reference as a vertical array. + * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the + * reference of the cell in which the ROW function appears; otherwise this function returns 0. + * + * @param cellAddress A reference to a range of cells for which you want the row numbers + * @return integer or array of integer + */ + public static function ROW($cellAddress=Null) { + if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } + + if (is_array($cellAddress)) { + foreach($cellAddress as $columnKey => $rowValue) { + foreach($rowValue as $rowKey => $cellValue) { + return (integer) preg_replace('/[^0-9]/i','',$rowKey); + } + } + } else { + if (strpos($cellAddress,'!') !== false) { + list($sheet,$cellAddress) = explode('!',$cellAddress); + } + if (strpos($cellAddress,':') !== false) { + list($startAddress,$endAddress) = explode(':',$cellAddress); + $startAddress = preg_replace('/[^0-9]/','',$startAddress); + $endAddress = preg_replace('/[^0-9]/','',$endAddress); + $returnValue = array(); + do { + $returnValue[][] = (integer) $startAddress; + } while ($startAddress++ != $endAddress); + return $returnValue; + } else { + list($cellAddress) = explode(':',$cellAddress); + return (integer) preg_replace('/[^0-9]/','',$cellAddress); } } } // function ROW() + /** + * ROWS + * + * Returns the number of rows in an array or reference. + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows + * @return integer + */ + public static function ROWS($cellAddress=Null) { + if (is_null($cellAddress) || $cellAddress === '') { + return 1; + } elseif (!is_array($cellAddress)) { + return self::$_errorCodes['value']; + } + + $isMatrix = (is_numeric(array_shift(array_keys($cellAddress)))); + list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); + + if ($isMatrix) { + return $columns; + } else { + return $rows; + } + } // function ROWS() + + + /** + * INDIRECT + * + * Returns the number of rows in an array or reference. + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows + * @return integer + */ + public static function INDIRECT($cellAddress=Null, PHPExcel_Cell $pCell = null) { + $cellAddress = self::flattenSingleValue($cellAddress); + if (is_null($cellAddress) || $cellAddress === '') { + return self::REF(); + } + + $cellAddress1 = $cellAddress; + $cellAddress2 = NULL; + if (strpos($cellAddress,':') !== false) { + list($cellAddress1,$cellAddress2) = explode(':',$cellAddress); + } + + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress1, $matches)) || + ((!is_null($cellAddress2)) && (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress2, $matches)))) { + return self::REF(); + } + + if (strpos($cellAddress,'!') !== false) { + list($sheetName,$cellAddress) = explode('!',$cellAddress); + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); + } // function INDIRECT() + + + /** + * OFFSET + * + * Returns a reference to a range that is a specified number of rows and columns from a cell or range of cells. + * The reference that is returned can be a single cell or a range of cells. You can specify the number of rows and + * the number of columns to be returned. + * + * @param cellAddress The reference from which you want to base the offset. Reference must refer to a cell or + * range of adjacent cells; otherwise, OFFSET returns the #VALUE! error value. + * @param rows The number of rows, up or down, that you want the upper-left cell to refer to. + * Using 5 as the rows argument specifies that the upper-left cell in the reference is + * five rows below reference. Rows can be positive (which means below the starting reference) + * or negative (which means above the starting reference). + * @param cols The number of columns, to the left or right, that you want the upper-left cell of the result + * to refer to. Using 5 as the cols argument specifies that the upper-left cell in the + * reference is five columns to the right of reference. Cols can be positive (which means + * to the right of the starting reference) or negative (which means to the left of the + * starting reference). + * @param height The height, in number of rows, that you want the returned reference to be. Height must be a positive number. + * @param width The width, in number of columns, that you want the returned reference to be. Width must be a positive number. + * @return string A reference to a cell or range of cells + */ public static function OFFSET($cellAddress=Null,$rows=0,$columns=0,$height=null,$width=null) { if ($cellAddress == Null) { return 0; } - foreach($cellAddress as $startColumnKey => $rowValue) { - $startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumnKey); - foreach($rowValue as $startRowKey => $cellValue) { - break 2; - } - } - - foreach($cellAddress as $endColumnKey => $rowValue) { - foreach($rowValue as $endRowKey => $cellValue) { - } - } - $endColumnIndex = PHPExcel_Cell::columnIndexFromString($endColumnKey); - - $startColumnIndex += --$columns; - $startRowKey += $rows; - - if ($width == null) { - $endColumnIndex += $columns -1; - } else { - $endColumnIndex = $startColumnIndex + $width; - } - if ($height == null) { - $endRowKey += $rows; - } else { - $endRowKey = $startRowKey + $height -1; - } - - if (($startColumnIndex < 0) || ($startRowKey <= 0)) { + $pCell = array_pop(func_get_args()); + if (!is_object($pCell)) { return self::$_errorCodes['reference']; } - $startColumnKey = PHPExcel_Cell::stringFromColumnIndex($startColumnIndex); - $endColumnKey = PHPExcel_Cell::stringFromColumnIndex($endColumnIndex); - - $startCell = $startColumnKey.$startRowKey; - $endCell = $endColumnKey.$endRowKey; - - if ($startCell == $endCell) { - return $startColumnKey.$startRowKey; - } else { - return $startColumnKey.$startRowKey.':'.$endColumnKey.$endRowKey; + $sheetName = null; + if (strpos($cellAddress,"!")) { + list($sheetName,$cellAddress) = explode("!",$cellAddress); } + if (strpos($cellAddress,":")) { + list($startCell,$endCell) = explode(":",$cellAddress); + } else { + $startCell = $endCell = $cellAddress; + } + list($startCellColumn,$startCellRow) = PHPExcel_Cell::coordinateFromString($startCell); + list($endCellColumn,$endCellRow) = PHPExcel_Cell::coordinateFromString($endCell); + + $startCellRow += $rows; + $startCellColumn = PHPExcel_Cell::columnIndexFromString($startCellColumn) - 1; + $startCellColumn += $columns; + + if (($startCellRow <= 0) || ($startCellColumn < 0)) { + return self::$_errorCodes['reference']; + } + $endCellColumn = PHPExcel_Cell::columnIndexFromString($endCellColumn) - 1; + if (($width != null) && (!is_object($width))) { + $endCellColumn = $startCellColumn + $width - 1; + } else { + $endCellColumn += $columns; + } + $startCellColumn = PHPExcel_Cell::stringFromColumnIndex($startCellColumn); + + if (($height != null) && (!is_object($height))) { + $endCellRow = $startCellRow + $height - 1; + } else { + $endCellRow += $rows; + } + + if (($endCellRow <= 0) || ($endCellColumn < 0)) { + return self::$_errorCodes['reference']; + } + $endCellColumn = PHPExcel_Cell::stringFromColumnIndex($endCellColumn); + + $cellAddress = $startCellColumn.$startCellRow; + if (($startCellColumn != $endCellColumn) || ($startCellRow != $endCellRow)) { + $cellAddress .= ':'.$endCellColumn.$endCellRow; + } + + if ($sheetName !== null) { + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); } // function OFFSET() public static function CHOOSE() { $chooseArgs = func_get_args(); - $chosenEntry = self::flattenSingleValue(array_shift($chooseArgs)); + $chosenEntry = self::flattenArray(array_shift($chooseArgs)); $entryCount = count($chooseArgs) - 1; + if(is_array($chosenEntry)) { + $chosenEntry = array_shift($chosenEntry); + } if ((is_numeric($chosenEntry)) && (!is_bool($chosenEntry))) { --$chosenEntry; } else { @@ -9830,12 +10670,14 @@ class PHPExcel_Calculation_Functions { /** - * MATCH - * The MATCH function searches for a specified item in a range of cells - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_array The range of cells being searched - * @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. - * @return integer the relative position of the found item + * MATCH + * + * The MATCH function searches for a specified item in a range of cells + * + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_array The range of cells being searched + * @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. + * @return integer The relative position of the found item */ public static function MATCH($lookup_value, $lookup_array, $match_type=1) { @@ -9964,7 +10806,8 @@ class PHPExcel_Calculation_Functions { } $rowKeys = array_keys($arrayValues); - $columnKeys = array_keys($arrayValues[$rowKeys[0]]); + $columnKeys = @array_keys($arrayValues[$rowKeys[0]]); + if ($columnNum > count($columnKeys)) { return self::$_errorCodes['value']; } elseif ($columnNum == 0) { @@ -9974,7 +10817,15 @@ class PHPExcel_Calculation_Functions { $rowNum = $rowKeys[--$rowNum]; $returnArray = array(); foreach($arrayValues as $arrayColumn) { - $returnArray[] = $arrayColumn[$rowNum]; + if (is_array($arrayColumn)) { + if (isset($arrayColumn[$rowNum])) { + $returnArray[] = $arrayColumn[$rowNum]; + } else { + return $arrayValues[$rowNum]; + } + } else { + return $arrayValues[$rowNum]; + } } return $returnArray; } @@ -10009,7 +10860,7 @@ class PHPExcel_Calculation_Functions { // Calculate if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period))) { - if (($life < 1) || ($salvage < $life) || ($period > $life)) { + if (($life < 1) || ($period > $life)) { return self::$_errorCodes['num']; } return (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1)); @@ -10034,7 +10885,7 @@ class PHPExcel_Calculation_Functions { foreach($matrixData as $matrixRow) { $row = 0; foreach($matrixRow as $matrixCell) { - $returnMatrix[$column][$row] = $matrixCell; + $returnMatrix[$row][$column] = $matrixCell; ++$row; } ++$column; @@ -10162,6 +11013,37 @@ class PHPExcel_Calculation_Functions { } // function MDETERM() + /** + * SUMPRODUCT + * + * @param mixed $value Value to check + * @return float + */ + public static function SUMPRODUCT() { + $arrayList = func_get_args(); + + $wrkArray = self::flattenArray(array_shift($arrayList)); + $wrkCellCount = count($wrkArray); + + foreach($arrayList as $matrixData) { + $array2 = self::flattenArray($matrixData); + $count = count($array2); + if ($wrkCellCount != $count) { + return self::$_errorCodes['value']; + } + + foreach ($array2 as $i => $val) { + if (((is_numeric($wrkArray[$i])) && (!is_string($wrkArray[$i]))) && + ((is_numeric($val)) && (!is_string($val)))) { + $wrkArray[$i] *= $val; + } + } + } + + return array_sum($wrkArray); + } // function SUMPRODUCT() + + /** * SUMX2MY2 * @@ -10249,6 +11131,15 @@ class PHPExcel_Calculation_Functions { } // function SUMXMY2() + private static function _vlookupSort($a,$b) { + $firstColumn = array_shift(array_keys($a)); + if (strtolower($a[$firstColumn]) == strtolower($b[$firstColumn])) { + return 0; + } + return (strtolower($a[$firstColumn]) < strtolower($b[$firstColumn])) ? -1 : 1; + } // function _vlookupSort() + + /** * VLOOKUP * The VLOOKUP function searches for value in the left-most column of lookup_array and returns the value in the same row based on the index_number. @@ -10265,109 +11156,130 @@ class PHPExcel_Calculation_Functions { } // index_number must be less than or equal to the number of columns in lookup_array - if ($index_number > count($lookup_array)) { + if ((!is_array($lookup_array)) || (count($lookup_array) < 1)) { return self::$_errorCodes['reference']; - } - - // re-index lookup_array with numeric keys starting at 1 - array_unshift($lookup_array, array()); - $lookup_array = array_slice(array_values($lookup_array), 1, count($lookup_array), true); - - // look for an exact match - $row_number = array_search($lookup_value, $lookup_array[1]); - - // if an exact match is required, we have what we need to return an appropriate response - if ($not_exact_match == false) { - if ($row_number === false) { - return self::$_errorCodes['na']; + } else { + $firstRow = array_pop(array_keys($lookup_array)); + if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { + return self::$_errorCodes['reference']; } else { - return $lookup_array[$index_number][$row_number]; + $columnKeys = array_keys($lookup_array[$firstRow]); + $returnColumn = $columnKeys[--$index_number]; + $firstColumn = array_shift($columnKeys); + } + } + + if (!$not_exact_match) { + uasort($lookup_array,array('self','_vlookupSort')); + } + + $rowNumber = $rowValue = False; + foreach($lookup_array as $rowKey => $rowData) { + if (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)) { + break; + } + $rowNumber = $rowKey; + $rowValue = $rowData[$firstColumn]; + } + + if ($rowNumber !== false) { + if ((!$not_exact_match) && ($rowValue != $lookup_value)) { + // if an exact match is required, we have what we need to return an appropriate response + return self::$_errorCodes['na']; + } else { + // otherwise return the appropriate value + return $lookup_array[$rowNumber][$returnColumn]; } } - // TODO: The VLOOKUP spec in Excel states that, at this point, we should search for - // the highest value that is less than lookup_value. However, documentation on how string - // values should be treated here is sparse. return self::$_errorCodes['na']; } // function VLOOKUP() + /** - * LOOKUP - * The LOOKUP function searches for value either from a one-row or one-column range or from an array. - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_vector The range of cells being searched - * @param result_vector The column from which the matching value must be returned - * @return mixed The value of the found cell - */ + * LOOKUP + * The LOOKUP function searches for value either from a one-row or one-column range or from an array. + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_vector The range of cells being searched + * @param result_vector The column from which the matching value must be returned + * @return mixed The value of the found cell + */ public static function LOOKUP($lookup_value, $lookup_vector, $result_vector=null) { + $lookup_value = self::flattenSingleValue($lookup_value); - // check for LOOKUP Syntax (view Excel documentation) - if( is_null($result_vector) ) - { - // TODO: Syntax 2 (array) - } else { - // Syntax 1 (vector) - // get key (column or row) of lookup_vector - $kl = key($lookup_vector); - // check if lookup_value exists in lookup_vector - if( in_array($lookup_value, $lookup_vector[$kl]) ) - { - // FOUND IT! Get key of lookup_vector - $k_res = array_search($lookup_value, $lookup_vector[$kl]); - } else { - // value NOT FOUND - // Get the smallest value in lookup_vector - // The LOOKUP spec in Excel states --> IMPORTANT - The values in lookup_vector must be placed in ascending order! - $ksv = key($lookup_vector[$kl]); - $smallest_value = $lookup_vector[$kl][$ksv]; - // If lookup_value is smaller than the smallest value in lookup_vector, LOOKUP gives the #N/A error value. - if( $lookup_value < $smallest_value ) - { - return self::$_errorCodes['na']; - } else { - // If LOOKUP can't find the lookup_value, it matches the largest value in lookup_vector that is less than or equal to lookup_value. - // IMPORTANT : In Excel Documentation is not clear what happen if lookup_value is text! - foreach( $lookup_vector[$kl] AS $kk => $value ) - { - if( $lookup_value >= $value ) - { - $k_res = $kk; - } - } - } - } - - // Returns a value from the same position in result_vector - // get key (column or row) of result_vector - $kr = key($result_vector); - if( isset($result_vector[$kr][$k_res]) ) - { - return $result_vector[$kr][$k_res]; - } else { - // TODO: In Excel Documentation is not clear what happen here... - } + if (!is_array($lookup_vector)) { + return self::$_errorCodes['na']; } + $lookupRows = count($lookup_vector); + $lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]); + if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) { + $lookup_vector = self::TRANSPOSE($lookup_vector); + $lookupRows = count($lookup_vector); + $lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]); + } + + if (is_null($result_vector)) { + $result_vector = $lookup_vector; + } + $resultRows = count($result_vector); + $resultColumns = count($result_vector[array_shift(array_keys($result_vector))]); + if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) { + $result_vector = self::TRANSPOSE($result_vector); + $resultRows = count($result_vector); + $resultColumns = count($result_vector[array_shift(array_keys($result_vector))]); + } + + if ($lookupRows == 2) { + $result_vector = array_pop($lookup_vector); + $lookup_vector = array_shift($lookup_vector); + } + if ($lookupColumns != 2) { + foreach($lookup_vector as &$value) { + if (is_array($value)) { + $key1 = $key2 = array_shift(array_keys($value)); + $key2++; + $dataValue1 = $value[$key1]; + } else { + $key1 = 0; + $key2 = 1; + $dataValue1 = $value; + } + $dataValue2 = array_shift($result_vector); + if (is_array($dataValue2)) { + $dataValue2 = array_shift($dataValue2); + } + $value = array($key1 => $dataValue1, $key2 => $dataValue2); + } + unset($value); + } + + return self::VLOOKUP($lookup_value,$lookup_vector,2); } // function LOOKUP() /** - * Flatten multidemensional array + * Convert a multi-dimensional array to a simple 1-dimensional array * - * @param array $array Array to be flattened - * @return array Flattened array + * @param array $array Array to be flattened + * @return array Flattened array */ public static function flattenArray($array) { - if(!is_array ( $array ) ){ - $array = array ( $array ); + if (!is_array($array)) { + return (array) $array; } $arrayValues = array(); - foreach ($array as $value) { - if (is_scalar($value)) { - $arrayValues[] = self::flattenSingleValue($value); - } elseif (is_array($value)) { - $arrayValues = array_merge($arrayValues, self::flattenArray($value)); + if (is_array($value)) { + foreach ($value as $val) { + if (is_array($val)) { + foreach ($val as $v) { + $arrayValues[] = $v; + } + } else { + $arrayValues[] = $val; + } + } } else { $arrayValues[] = $value; } @@ -10378,14 +11290,46 @@ class PHPExcel_Calculation_Functions { /** - * Convert an array with one element to a flat value + * Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing * - * @param mixed $value Array or flat value - * @return mixed + * @param array $array Array to be flattened + * @return array Flattened array + */ + public static function flattenArrayIndexed($array) { + if (!is_array($array)) { + return (array) $array; + } + + $arrayValues = array(); + foreach ($array as $k1 => $value) { + if (is_array($value)) { + foreach ($value as $k2 => $val) { + if (is_array($val)) { + foreach ($val as $k3 => $v) { + $arrayValues[$k1.'.'.$k2.'.'.$k3] = $v; + } + } else { + $arrayValues[$k1.'.'.$k2] = $val; + } + } + } else { + $arrayValues[$k1] = $value; + } + } + + return $arrayValues; + } // function flattenArrayIndexed() + + + /** + * Convert an array to a single scalar value by extracting the first element + * + * @param mixed $value Array or scalar value + * @return mixed */ public static function flattenSingleValue($value = '') { if (is_array($value)) { - $value = self::flattenSingleValue(array_pop($value)); + return self::flattenSingleValue(array_pop($value)); } return $value; } // function flattenSingleValue() @@ -10503,3 +11447,34 @@ if (!function_exists('money_format')) { return $format; } // function money_format() } + + +// +// Strangely, PHP doesn't have a mb_str_replace multibyte function +// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set +// +if ((!function_exists('mb_str_replace')) && + (function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) { + function mb_str_replace($search, $replace, $subject) { + if(is_array($subject)) { + $ret = array(); + foreach($subject as $key => $val) { + $ret[$key] = mb_str_replace($search, $replace, $val); + } + return $ret; + } + + foreach((array) $search as $key => $s) { + if($s == '') { + continue; + } + $r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : ''); + $pos = mb_strpos($subject, $s, 0, 'UTF-8'); + while($pos !== false) { + $subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8'); + $pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8'); + } + } + return $subject; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Cell.php b/libraries/PHPExcel/PHPExcel/Cell.php index 9b321822a..c0603ac16 100644 --- a/libraries/PHPExcel/PHPExcel/Cell.php +++ b/libraries/PHPExcel/PHPExcel/Cell.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -64,7 +64,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell { @@ -136,11 +136,6 @@ class PHPExcel_Cell */ public function __construct($pColumn = 'A', $pRow = 1, $pValue = null, $pDataType = null, PHPExcel_Worksheet $pSheet = null) { - // Set value binder? - if (is_null(self::$_valueBinder)) { - self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder(); - } - // Initialise cell coordinate $this->_column = strtoupper($pColumn); $this->_row = $pRow; @@ -171,7 +166,7 @@ class PHPExcel_Cell */ public function getColumn() { - return strtoupper($this->_column); + return $this->_column; } /** @@ -226,22 +221,42 @@ class PHPExcel_Cell * @param mixed $pValue Value * @param string $pDataType Explicit data type * @return PHPExcel_Cell + * @throws Exception */ public function setValueExplicit($pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING) { - // check strings that they are ok - // TODO: fix also for RichText - if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING && !($pValue instanceof PHPExcel_RichText)) { - // string must never be longer than 32,767 characters, truncate if necessary - $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); + // set the value according to data type + switch ($pDataType) { + case PHPExcel_Cell_DataType::TYPE_STRING: + case PHPExcel_Cell_DataType::TYPE_NULL: + case PHPExcel_Cell_DataType::TYPE_INLINE: + $this->_value = PHPExcel_Cell_DataType::checkString($pValue); + break; - // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" - $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); + case PHPExcel_Cell_DataType::TYPE_NUMERIC: + $this->_value = (float)$pValue; + break; + + case PHPExcel_Cell_DataType::TYPE_FORMULA: + $this->_value = (string)$pValue; + break; + + case PHPExcel_Cell_DataType::TYPE_BOOL: + $this->_value = (bool)$pValue; + break; + + case PHPExcel_Cell_DataType::TYPE_ERROR: + $this->_value = PHPExcel_Cell_DataType::checkErrorCode($pValue); + break; + + default: + throw new Exception('Invalid datatype: ' . $pDataType); + break; } - $this->_value = $pValue; - $this->_dataType = $pDataType; - return $this; + // set the datatype + $this->_dataType = $pDataType; + return $this; } /** @@ -492,22 +507,17 @@ class PHPExcel_Cell { if (strpos($pCoordinateString,':') !== false) { throw new Exception('Cell coordinate string can not be a range of cells.'); + } else if ($pCoordinateString == '') { throw new Exception('Cell coordinate can not be zero-length string.'); - } else { - // Column - $column = ''; - // Row - $row = ''; - - // Convert a cell reference - if (preg_match("/([$]?[A-Z]+)([$]?\d+)/", $pCoordinateString, $matches)) { - list(, $column, $row) = $matches; - } - - // Return array + } else if (preg_match("/([$]?[A-Z]+)([$]?\d+)/", $pCoordinateString, $matches)) { + list(, $column, $row) = $matches; return array($column, $row); + + } else { + throw new Exception('Invalid cell coordinate.'); + } } @@ -745,6 +755,10 @@ class PHPExcel_Cell * @return PHPExcel_Cell_IValueBinder */ public static function getValueBinder() { + if (is_null(self::$_valueBinder)) { + self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder(); + } + return self::$_valueBinder; } diff --git a/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php index f2c4019d3..d8e25645c 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder { @@ -124,21 +124,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder return true; } } - - // Style logic - Numbers - if ($dataType === PHPExcel_Cell_DataType::TYPE_NUMERIC) { - // Leading zeroes? - if (preg_match('/^\-?[0]+[0-9]*\.?[0-9]*$/', $value)) { - // Convert value to string - $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_STRING); - - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_TEXT ); - - return true; - } - } - + // Not bound yet? Use parent... return parent::bindValue($cell, $value); } diff --git a/libraries/PHPExcel/PHPExcel/Cell/DataType.php b/libraries/PHPExcel/PHPExcel/Cell/DataType.php index cfe35765f..add1bec8b 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DataType.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DataType.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DefaultValueBinder.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DataType { @@ -82,4 +82,44 @@ class PHPExcel_Cell_DataType public static function dataTypeForValue($pValue = null) { return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue); } + + /** + * Check a string that it satisfies Excel requirements + * + * @param mixed Value to sanitize to an Excel string + * @return mixed Sanitized value + */ + public static function checkString($pValue = null) + { + if ($pValue instanceof PHPExcel_RichText) { + // TODO: Sanitize Rich-Text string (max. character count is 32,767) + return $pValue; + } + + // string must never be longer than 32,767 characters, truncate if necessary + $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); + + // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" + $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); + + return $pValue; + } + + /** + * Check a value that it is a valid error code + * + * @param mixed Value to sanitize to an Excel error code + * @return string Sanitized value + */ + public static function checkErrorCode($pValue = null) + { + $pValue = (string)$pValue; + + if ( !array_key_exists($pValue, self::$_errorCodes) ) { + $pValue = '#NULL!'; + } + + return $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php b/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php index 234a93d6c..8d7f29329 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DataValidation { diff --git a/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php index 29b0f6631..2b8bef72e 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder { @@ -87,22 +87,31 @@ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder // Match the value against a few data types if (is_null($pValue)) { return PHPExcel_Cell_DataType::TYPE_NULL; + } elseif ($pValue === '') { return PHPExcel_Cell_DataType::TYPE_STRING; + } elseif ($pValue instanceof PHPExcel_RichText) { return PHPExcel_Cell_DataType::TYPE_STRING; + } elseif ($pValue{0} === '=') { return PHPExcel_Cell_DataType::TYPE_FORMULA; + } elseif (is_bool($pValue)) { return PHPExcel_Cell_DataType::TYPE_BOOL; + } elseif (is_float($pValue) || is_int($pValue)) { return PHPExcel_Cell_DataType::TYPE_NUMERIC; - } elseif (preg_match('/^\-?[0-9]*\\.?[0-9]*$/', $pValue)) { + + } elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) { return PHPExcel_Cell_DataType::TYPE_NUMERIC; + } elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { return PHPExcel_Cell_DataType::TYPE_ERROR; + } else { return PHPExcel_Cell_DataType::TYPE_STRING; + } } } diff --git a/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php b/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php index 122424490..a4f3758f4 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php +++ b/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_Hyperlink { diff --git a/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php index 479ed6920..3a4186ccf 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Cell_IValueBinder { diff --git a/libraries/PHPExcel/PHPExcel/Comment.php b/libraries/PHPExcel/PHPExcel/Comment.php index ea6cdb4b7..ee7254ac0 100644 --- a/libraries/PHPExcel/PHPExcel/Comment.php +++ b/libraries/PHPExcel/PHPExcel/Comment.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Comment implements PHPExcel_IComparable { @@ -290,37 +290,6 @@ class PHPExcel_Comment implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/DocumentProperties.php b/libraries/PHPExcel/PHPExcel/DocumentProperties.php index 609108dd1..41fe1fb7d 100644 --- a/libraries/PHPExcel/PHPExcel/DocumentProperties.php +++ b/libraries/PHPExcel/PHPExcel/DocumentProperties.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_DocumentProperties { diff --git a/libraries/PHPExcel/PHPExcel/DocumentSecurity.php b/libraries/PHPExcel/PHPExcel/DocumentSecurity.php index 65c64742f..6344d40e3 100644 --- a/libraries/PHPExcel/PHPExcel/DocumentSecurity.php +++ b/libraries/PHPExcel/PHPExcel/DocumentSecurity.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_DocumentSecurity { diff --git a/libraries/PHPExcel/PHPExcel/HashTable.php b/libraries/PHPExcel/PHPExcel/HashTable.php index b516f7998..afbced953 100644 --- a/libraries/PHPExcel/PHPExcel/HashTable.php +++ b/libraries/PHPExcel/PHPExcel/HashTable.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_HashTable { @@ -101,26 +101,10 @@ class PHPExcel_HashTable * @throws Exception */ public function add(PHPExcel_IComparable $pSource = null) { - // Determine hashcode - $hashCode = null; - $hashIndex = $pSource->getHashIndex(); - if ( is_null ( $hashIndex ) ) { - $hashCode = $pSource->getHashCode(); - } else if ( isset ( $this->_keyMap[$hashIndex] ) ) { - $hashCode = $this->_keyMap[$hashIndex]; - } else { - $hashCode = $pSource->getHashCode(); - } - - // Add value - if (!isset($this->_items[ $hashCode ])) { - $this->_items[ $hashCode ] = $pSource; - $index = count($this->_items) - 1; - $this->_keyMap[ $index ] = $hashCode; - $pSource->setHashIndex( $index ); - } else { - $pSource->setHashIndex( $this->_items[ $hashCode ]->getHashIndex() ); - } + if (!isset($this->_items[ $pSource->getHashCode() ])) { + $this->_items[ $pSource->getHashCode() ] = $pSource; + $this->_keyMap[ count($this->_items) - 1 ] = $pSource->getHashCode(); + } } /** diff --git a/libraries/PHPExcel/PHPExcel/IComparable.php b/libraries/PHPExcel/PHPExcel/IComparable.php index f02271fca..1a3a689ea 100644 --- a/libraries/PHPExcel/PHPExcel/IComparable.php +++ b/libraries/PHPExcel/PHPExcel/IComparable.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -29,7 +29,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_IComparable { @@ -39,24 +39,5 @@ interface PHPExcel_IComparable * @return string Hash code */ public function getHashCode(); - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex(); - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value); + } diff --git a/libraries/PHPExcel/PHPExcel/IOFactory.php b/libraries/PHPExcel/PHPExcel/IOFactory.php index e3a623080..f116bc012 100644 --- a/libraries/PHPExcel/PHPExcel/IOFactory.php +++ b/libraries/PHPExcel/PHPExcel/IOFactory.php @@ -2,27 +2,27 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,10 +49,10 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_IOFactory -{ +{ /** * Search locations * @@ -62,24 +62,27 @@ class PHPExcel_IOFactory array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) ); - + /** * Autoresolve classes - * + * * @var array */ private static $_autoResolveClasses = array( 'Excel2007', 'Excel5', + 'Excel2003XML', + 'OOCalc', + 'SYLK', 'Serialized', - 'CSV' + 'CSV', ); - + /** * Private constructor for PHPExcel_IOFactory */ private function __construct() { } - + /** * Get search locations * @@ -88,10 +91,10 @@ class PHPExcel_IOFactory public static function getSearchLocations() { return self::$_searchLocations; } - + /** * Set search locations - * + * * @param array $value * @throws Exception */ @@ -102,10 +105,10 @@ class PHPExcel_IOFactory throw new Exception('Invalid parameter passed.'); } } - + /** * Add search location - * + * * @param string $type Example: IWriter * @param string $location Example: PHPExcel/Writer/{0}.php * @param string $classname Example: PHPExcel_Writer_{0} @@ -113,7 +116,7 @@ class PHPExcel_IOFactory public static function addSearchLocation($type = '', $location = '', $classname = '') { self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); } - + /** * Create PHPExcel_Writer_IWriter * @@ -124,28 +127,28 @@ class PHPExcel_IOFactory public static function createWriter(PHPExcel $phpExcel, $writerType = '') { // Search type $searchType = 'IWriter'; - + // Include class foreach (self::$_searchLocations as $searchLocation) { if ($searchLocation['type'] == $searchType) { $className = str_replace('{0}', $writerType, $searchLocation['class']); $classFile = str_replace('{0}', $writerType, $searchLocation['path']); - + if (!class_exists($className)) { require_once PHPEXCEL_ROOT . $classFile; } - + $instance = new $className($phpExcel); if (!is_null($instance)) { return $instance; } } } - + // Nothing found... throw new Exception("No $searchType found for type $writerType"); } - + /** * Create PHPExcel_Reader_IReader * @@ -155,34 +158,34 @@ class PHPExcel_IOFactory public static function createReader($readerType = '') { // Search type $searchType = 'IReader'; - + // Include class foreach (self::$_searchLocations as $searchLocation) { if ($searchLocation['type'] == $searchType) { $className = str_replace('{0}', $readerType, $searchLocation['class']); $classFile = str_replace('{0}', $readerType, $searchLocation['path']); - + if (!class_exists($className)) { require_once PHPEXCEL_ROOT . $classFile; } - + $instance = new $className(); if (!is_null($instance)) { return $instance; } } } - + // Nothing found... throw new Exception("No $searchType found for type $readerType"); } - + /** * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution * * @param string $pFileName * @return PHPExcel - */ + */ public static function load($pFilename) { $reader = self::createReaderForFile($pFilename); return $reader->load($pFilename); @@ -193,9 +196,55 @@ class PHPExcel_IOFactory * * @param string $pFileName * @return PHPExcel_Reader_IReader - * @throws Exception - */ + */ public static function createReaderForFile($pFilename) { + + // First, lucky guess by inspecting file extension + $pathinfo = pathinfo($pFilename); + + if (isset($pathinfo['extension'])) { + + switch (strtolower($pathinfo['extension'])) { + case 'xlsx': + $reader = self::createReader('Excel2007'); + break; + + case 'xls': + $reader = self::createReader('Excel5'); + break; + + case 'ods': + $reader = self::createReader('OOCalc'); + break; + + case 'slk': + $reader = self::createReader('SYLK'); + break; + + case 'xml': + $reader = self::createReader('Excel2003XML'); + break; + + case 'csv': + // Do nothing + // We must not try to use CSV reader since it loads + // all files including Excel files etc. + break; + + default: + break; + + } + + // Let's see if we are lucky + if ($reader->canRead($pFilename)) { + return $reader; + } + + } + + // If we reach here then "lucky guess" didn't give any result + // Try loading using self::$_autoResolveClasses foreach (self::$_autoResolveClasses as $autoResolveClass) { $reader = self::createReader($autoResolveClass); @@ -204,6 +253,5 @@ class PHPExcel_IOFactory } } - throw new Exception("Could not automatically determine PHPExcel_Reader_IReader for file."); } } diff --git a/libraries/PHPExcel/PHPExcel/NamedRange.php b/libraries/PHPExcel/PHPExcel/NamedRange.php index ba6ad281e..87054a5f8 100644 --- a/libraries/PHPExcel/PHPExcel/NamedRange.php +++ b/libraries/PHPExcel/PHPExcel/NamedRange.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_NamedRange { diff --git a/libraries/PHPExcel/PHPExcel/Reader/CSV.php b/libraries/PHPExcel/PHPExcel/Reader/CSV.php index 30e894b6b..8758112fb 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/CSV.php +++ b/libraries/PHPExcel/PHPExcel/Reader/CSV.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,10 +55,17 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader { + /** + * Input encoding + * + * @var string + */ + private $_inputEncoding; + /** * Delimiter * @@ -98,6 +105,7 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader * Create a new PHPExcel_Reader_CSV */ public function __construct() { + $this->_inputEncoding = 'UTF-8'; $this->_delimiter = ','; $this->_enclosure = '"'; $this->_lineEnding = PHP_EOL; @@ -117,9 +125,8 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader if (!file_exists($pFilename)) { throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); } - - // Check if it is a CSV file (using file name) - return (substr(strtolower($pFilename), -3) == 'csv'); + + return true; } /** @@ -155,6 +162,26 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader $this->_readFilter = $pValue; } + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'UTF-8') + { + $this->_inputEncoding = $pValue; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + /** * Loads PHPExcel from file into PHPExcel instance * @@ -181,7 +208,18 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader throw new Exception("Could not open file $pFilename for reading."); } - // Loop trough file + // Skip BOM, if any + switch ($this->_inputEncoding) { + case 'UTF-8': + fgets($fileHandle, 4) == "\xEF\xBB\xBF" ? + fseek($fileHandle, 3) : fseek($fileHandle, 0); + break; + + default: + break; + } + + // Loop through file $currentRow = 0; $rowData = array(); while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { @@ -193,6 +231,11 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Unescape enclosures $rowData[$i] = str_replace("\\" . $this->_enclosure, $this->_enclosure, $rowData[$i]); $rowData[$i] = str_replace($this->_enclosure . $this->_enclosure, $this->_enclosure, $rowData[$i]); + + // Convert encoding if necessary + if ($this->_inputEncoding !== 'UTF-8') { + $rowData[$i] = PHPExcel_Shared_String::ConvertEncoding($rowData[$i], 'UTF-8', $this->_inputEncoding); + } // Set cell value $objPHPExcel->getActiveSheet()->setCellValue( diff --git a/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php b/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php index 8d8d83488..63c5ae3cc 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php +++ b/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReadFilter.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter { diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php b/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php new file mode 100644 index 000000000..89d5a83c3 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php @@ -0,0 +1,698 @@ +_readDataOnly; + } + + /** + * Set read data only + * + * @param boolean $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadDataOnly($pValue = false) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Get which sheets to load + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadSheetsOnly($value = null) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = null; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Create a new PHPExcel_Reader_Excel2003XML + */ + public function __construct() { + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + +// Office xmlns:o="urn:schemas-microsoft-com:office:office" +// Excel xmlns:x="urn:schemas-microsoft-com:office:excel" +// XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" +// Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" +// XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" +// XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" +// MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" +// Rowset xmlns:z="#RowsetSchema" +// + + $signature = array( + '', + '' + ); + + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Read sample data (first 2 KB will do) + $fh = fopen($pFilename, 'r'); + $data = fread($fh, 2048); + fclose($fh); + + $headers = explode("\n",$data); + $valid = true; + foreach($signature as $key => $match) { + if (isset($headers[$key])) { + $line = trim(rtrim($headers[$key], "\r\n")); + if ($line != $match) { + $valid = false; + break; + } + } else { + $valid = false; + break; + } + } + + return $valid; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + /** + * pixel units to excel width units(units of 1/256th of a character width) + * @param pxs + * @return + */ + private static function _pixel2WidthUnits($pxs) { + $UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); + + $widthUnits = 256 * ($pxs / 7); + $widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; + return $widthUnits; + } + + /** + * excel width units(units of 1/256th of a character width) to pixel units + * @param widthUnits + * @return + */ + private static function _widthUnits2Pixel($widthUnits) { + $pixels = ($widthUnits / 256) * 7; + $offsetWidthUnits = $widthUnits % 256; + $pixels += round($offsetWidthUnits / (256 / 7)); + return $pixels; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); + + $underlineStyles = array ( + PHPExcel_Style_Font::UNDERLINE_NONE, + PHPExcel_Style_Font::UNDERLINE_DOUBLE, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, + PHPExcel_Style_Font::UNDERLINE_SINGLE, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING + ); + $verticalAlignmentStyles = array ( + PHPExcel_Style_Alignment::VERTICAL_BOTTOM, + PHPExcel_Style_Alignment::VERTICAL_TOP, + PHPExcel_Style_Alignment::VERTICAL_CENTER, + PHPExcel_Style_Alignment::VERTICAL_JUSTIFY + ); + $horizontalAlignmentStyles = array ( + PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, + PHPExcel_Style_Alignment::HORIZONTAL_LEFT, + PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, + PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY + ); + + + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $xml = simplexml_load_file($pFilename); + $namespaces = $xml->getNamespaces(true); +// echo '
';
+//		print_r($namespaces);
+//		echo '

'; +// +// echo '
';
+//		print_r($xml);
+//		echo '

'; +// + $docProps = $objPHPExcel->getProperties(); + foreach($xml->DocumentProperties[0] as $propertyName => $propertyValue) { + switch ($propertyName) { + case 'Title' : + $docProps->setTitle($propertyValue); + break; + case 'Subject' : + $docProps->setSubject($propertyValue); + break; + case 'Author' : + $docProps->setCreator($propertyValue); + break; + case 'Created' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'LastAuthor' : + $docProps->setLastModifiedBy($propertyValue); + break; + case 'Company' : + $docProps->setCompany($propertyValue); + break; + case 'Category' : + $docProps->setCategory($propertyValue); + break; + case 'Keywords' : + $docProps->setKeywords($propertyValue); + break; + case 'Description' : + $docProps->setDescription($propertyValue); + break; + } + } + + + foreach($xml->Styles[0] as $style) { + $style_ss = $style->attributes($namespaces['ss']); + $styleID = (string) $style_ss['ID']; +// echo 'Style ID = '.$styleID.'
'; + if ($styleID == 'Default') { + $this->_styles['Default'] = array(); + } else { + $this->_styles[$styleID] = $this->_styles['Default']; + } + foreach ($style as $styleType => $styleData) { + $styleAttributes = $styleData->attributes($namespaces['ss']); +// echo $styleType.'
'; + switch ($styleType) { + case 'Alignment' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'Vertical' : + if (self::identifyFixedStyleValue($verticalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; + } + break; + case 'Horizontal' : + if (self::identifyFixedStyleValue($horizontalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; + } + break; + case 'WrapText' : + $this->_styles[$styleID]['alignment']['wrap'] = true; + break; + } + } + break; + case 'Borders' : + foreach($styleData->Border as $borderStyle) { + $borderAttributes = $borderStyle->attributes($namespaces['ss']); + $thisBorder = array(); + foreach($borderAttributes as $borderStyleKey => $borderStyleValue) { +// echo $borderStyleKey.' = '.$borderStyleValue.'
'; + switch ($borderStyleKey) { + case 'LineStyle' : + $thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Weight' : +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Position' : + $borderPosition = strtolower($borderStyleValue); + break; + case 'Color' : + $borderColour = substr($borderStyleValue,1); + $thisBorder['color']['rgb'] = $borderColour; + break; + } + } + if (count($thisBorder) > 0) { + if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { + $this->_styles[$styleID]['borders'][$borderPosition] = $thisBorder; + } + } + } + break; + case 'Font' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'FontName' : + $this->_styles[$styleID]['font']['name'] = $styleAttributeValue; + break; + case 'Size' : + $this->_styles[$styleID]['font']['size'] = $styleAttributeValue; + break; + case 'Color' : + $this->_styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue,1); + break; + case 'Bold' : + $this->_styles[$styleID]['font']['bold'] = true; + break; + case 'Italic' : + $this->_styles[$styleID]['font']['italic'] = true; + break; + case 'Underline' : + if (self::identifyFixedStyleValue($underlineStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['font']['underline'] = $styleAttributeValue; + } + break; + } + } + break; + case 'Interior' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + switch ($styleAttributeKey) { + case 'Color' : + $this->_styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue,1); + break; + } + } + break; + case 'NumberFormat' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = str_replace($fromFormats,$toFormats,$styleAttributeValue); + switch ($styleAttributeValue) { + case 'Short Date' : + $styleAttributeValue = 'dd/mm/yyyy'; + break; + } + if ($styleAttributeValue > '') { + $this->_styles[$styleID]['numberformat']['code'] = $styleAttributeValue; + } + } + break; + case 'Protection' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + } + break; + } + } +// print_r($this->_styles[$styleID]); +// echo '
'; + } +// echo '
'; + + $worksheetID = 0; + foreach($xml->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + if ((isset($this->_loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && + (!in_array($worksheet_ss['Name'], $this->_loadSheetsOnly))) { + continue; + } + + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheet_ss['Name'])) { + $worksheetName = $worksheet_ss['Name']; + $objPHPExcel->getActiveSheet()->setTitle($worksheetName); + } + + $columnID = 'A'; + foreach($worksheet->Table->Column as $columnData) { + $columnData_ss = $columnData->attributes($namespaces['ss']); + if (isset($columnData_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); + } + if (isset($columnData_ss['Width'])) { + $columnWidth = $columnData_ss['Width']; +// echo 'Setting column width for '.$columnID.' to '.$columnWidth.'
'; + $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); + } + ++$columnID; + } + + $rowID = 1; + foreach($worksheet->Table->Row as $rowData) { + $row_ss = $rowData->attributes($namespaces['ss']); + if (isset($row_ss['Index'])) { + $rowID = (integer) $row_ss['Index']; + } +// echo 'Row '.$rowID.'
'; + if (isset($row_ss['StyleID'])) { + $rowStyle = $row_ss['StyleID']; + } + if (isset($row_ss['Height'])) { + $rowHeight = $row_ss['Height']; +// echo 'Setting row height to '.$rowHeight.'
'; + $objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); + } + $columnID = 'A'; + foreach($rowData->Cell as $cell) { + + $cell_ss = $cell->attributes($namespaces['ss']); + if (isset($cell_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); + } + $cellRange = $columnID.$rowID; + + if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { + $columnTo = $columnID; + if (isset($cell_ss['MergeAcross'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); + } + $rowTo = $rowID; + if (isset($cell_ss['MergeDown'])) { + $rowTo = $rowTo + $cell_ss['MergeDown']; + } + $cellRange .= ':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cell_ss['Formula'])) { + $cellDataFormula = $cell_ss['Formula']; + $hasCalculatedValue = true; + } + if (isset($cell->Data)) { + $cellValue = $cellData = $cell->Data; + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $cellData_ss = $cellData->attributes($namespaces['ss']); + if (isset($cellData_ss['Type'])) { + $cellDataType = $cellData_ss['Type']; + switch ($cellDataType) { + /* + const TYPE_STRING = 's'; + const TYPE_FORMULA = 'f'; + const TYPE_NUMERIC = 'n'; + const TYPE_BOOL = 'b'; + const TYPE_NULL = 's'; + const TYPE_INLINE = 'inlineStr'; + const TYPE_ERROR = 'e'; + */ + case 'String' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + case 'Number' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = (float) $cellValue; + if (floor($cellValue) == $cellValue) { + $cellValue = (integer) $cellValue; + } + break; + case 'Boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cellValue = ($cellValue != 0); + break; + case 'DateTime' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); + break; + case 'Error' : + $type = PHPExcel_Cell_DataType::TYPE_ERROR; + break; + } + } + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + $columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); + // Convert R1C1 style references to A1 style references (but only when not quoted) + $temp = explode('"',$cellDataFormula); + foreach($temp as $key => &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if (($key % 2) == 0) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $rowID; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $rowID + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $columnNumber; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $columnNumber + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); + } + +// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'
'; +// + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$cellValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); + } + } + if (isset($cell_ss['StyleID'])) { + $style = (string) $cell_ss['StyleID']; +// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'
'; + if ((isset($this->_styles[$style])) && (count($this->_styles[$style]) > 0)) { +// echo 'Cell '.$columnID.$rowID.'
'; +// print_r($this->_styles[$style]); +// echo '
'; + if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { + $objPHPExcel->getActiveSheet()->setCellValue($columnID.$rowID,NULL); + } + $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->_styles[$style]); + } + } + ++$columnID; + } + ++$rowID; + } + ++$worksheetID; + } + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_Excel2003XML + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php b/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php index cd0d5c1f2..6cbc89372 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -94,7 +94,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader { @@ -217,7 +217,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $zip = new ZipArchive; if ($zip->open($pFilename) === true) { // check if it is an OOXML archive - $rels = simplexml_load_string($zip->getFromName("_rels/.rels")); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); $zip->close(); @@ -227,7 +227,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader return false; } - private function _castToBool($c) { // echo 'Initial Cast to Boolean
'; $value = isset($c->v) ? (string) $c->v : null; @@ -299,7 +298,33 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + + public function _getFromZipArchive(ZipArchive $archive, $fileName = '') + { + // Root-relative paths + if (strpos($fileName, '//') !== false) + { + $fileName = substr($fileName, strpos($fileName, '//') + 1); + } + $fileName = PHPExcel_Shared_File::realpath($fileName); + + // Apache POI fixes + $contents = $archive->getFromName($fileName); + if ($contents === false) + { + $contents = $archive->getFromName(substr($fileName, 1)); + } + + /* + if (strpos($contents, 'open($pFilename); - $rels = simplexml_load_string($zip->getFromName("_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($rels->Relationship as $rel) { switch ($rel["Type"]) { case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": - $xmlCore = simplexml_load_string($zip->getFromName("{$rel['Target']}")); - if ($xmlCore === false) { // Apache POI hack - $xmlCore = simplexml_load_string($zip->getFromName(substr("{$rel['Target']}", 1))); - } + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); if ($xmlCore) { $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); @@ -351,15 +373,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": $dir = dirname($rel["Target"]); - $relsWorkbook = simplexml_load_string($zip->getFromName("$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - if ($relsWorkbook === false) { // Apache POI hack - $relsWorkbook = simplexml_load_string($zip->getFromName(substr("$dir/_rels/" . basename($rel["Target"]) . ".rels", 1))); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - } + $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); $sharedStrings = array(); $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); - $xmlStrings = simplexml_load_string($zip->getFromName("$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlStrings = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); if (isset($xmlStrings) && isset($xmlStrings->si)) { foreach ($xmlStrings->si as $val) { if (isset($val->t)) { @@ -380,7 +399,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $styles = array(); $cellStyles = array(); $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); - $xmlStyles = simplexml_load_string($zip->getFromName("$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlStyles = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); $numFmts = null; if ($xmlStyles && $xmlStyles->numFmts[0]) { $numFmts = $xmlStyles->numFmts[0]; @@ -415,12 +434,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader "border" => $xmlStyles->borders->border[intval($xf["borderId"])], "alignment" => $xf->alignment, "protection" => $xf->protection, - "applyAlignment" => (isset($xf["applyAlignment"]) && ((string)$xf["applyAlignment"] == 'true' || (string)$xf["applyAlignment"] == '1')), - "applyBorder" => (isset($xf["applyBorder"]) && ((string)$xf["applyBorder"] == 'true' || (string)$xf["applyBorder"] == '1')), - "applyFill" => (isset($xf["applyFill"]) && ((string)$xf["applyFill"] == 'true' || (string)$xf["applyFill"] == '1')), - "applyFont" => (isset($xf["applyFont"]) && ((string)$xf["applyFont"] == 'true' || (string)$xf["applyFont"] == '1')), - "applyNumberFormat" => (isset($xf["applyNumberFormat"]) && ((string)$xf["applyNumberFormat"] == 'true' || (string)$xf["applyNumberFormat"] == '1')), - "applyProtection" => (isset($xf["applyProtection"]) && ((string)$xf["applyProtection"] == 'true' || (string)$xf["applyProtection"] == '1')) ); $styles[] = $style; @@ -448,12 +461,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader "border" => $xmlStyles->borders->border[intval($xf["borderId"])], "alignment" => $xf->alignment, "protection" => $xf->protection, - "applyAlignment" => true, - "applyBorder" => true, - "applyFill" => true, - "applyFont" => true, - "applyNumberFormat" => true, - "applyProtection" => true ); $cellStyles[] = $cellStyle; @@ -466,29 +473,32 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $dxfs = array(); if (!$this->_readDataOnly && $xmlStyles) { - foreach ($xmlStyles->dxfs->dxf as $dxf) { - $style = new PHPExcel_Style; - $this->_readStyle($style, $dxf); - $dxfs[] = $style; + if ($xmlStyles->dxfs) { + foreach ($xmlStyles->dxfs->dxf as $dxf) { + $style = new PHPExcel_Style; + $this->_readStyle($style, $dxf); + $dxfs[] = $style; + } } - foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { - if (intval($cellStyle['builtinId']) == 0) { - if (isset($cellStyles[intval($cellStyle['xfId'])])) { - // Set default style - $style = new PHPExcel_Style; - $this->_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); - - // normal style, currently not using it for anything + if ($xmlStyles->cellStyles) + { + foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { + if (intval($cellStyle['builtinId']) == 0) { + if (isset($cellStyles[intval($cellStyle['xfId'])])) { + // Set default style + $style = new PHPExcel_Style; + $this->_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); + + // normal style, currently not using it for anything + } } } } } - $xmlWorkbook = simplexml_load_string($zip->getFromName("{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - if ($xmlWorkbook === false) { // Apache POI hack - $xmlWorkbook = simplexml_load_string($zip->getFromName(substr("{$rel['Target']}", 1))); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - } + $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + // Set base date if ($xmlWorkbook->workbookPr) { PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); @@ -505,816 +515,857 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $countSkippedSheets = 0; // keep track of number of skipped sheets $mapSheetId = array(); // mapping of sheet ids from old to new - foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - ++$oldSheetId; - - // Check if sheet should be skipped - if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { - ++$countSkippedSheets; - $mapSheetId[$oldSheetId] = null; - continue; - } - - // Map old sheet id in original workbook to new sheet id. - // They will differ if loadSheetsOnly() is being used - $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; - - // Load sheet - $docSheet = $excel->createSheet(); - $docSheet->setTitle((string) $eleSheet["name"]); - $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $xmlSheet = simplexml_load_string($zip->getFromName("$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - - $sharedFormulas = array(); - - if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { - if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { - $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); + if ($xmlWorkbook->sheets) + { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + ++$oldSheetId; + + // Check if sheet should be skipped + if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { + ++$countSkippedSheets; + $mapSheetId[$oldSheetId] = null; + continue; } - - if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { - $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); + + // Map old sheet id in original workbook to new sheet id. + // They will differ if loadSheetsOnly() is being used + $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; + + // Load sheet + $docSheet = $excel->createSheet(); + $docSheet->setTitle((string) $eleSheet["name"]); + $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + $sharedFormulas = array(); + + if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { + $docSheet->setSheetState( (string) $eleSheet["state"] ); } - - if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { - $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false); - } - - if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { - $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false); - } - - if (isset($xmlSheet->sheetViews->sheetView->pane)) { - if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { - $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); - } else { - $xSplit = 0; - $ySplit = 0; - - if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { - $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); - } - - if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { - $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); - } - - $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); - } - } - } - - if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { - if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) { - $docSheet->setShowSummaryRight(false); - } else { - $docSheet->setShowSummaryRight(true); - } - - if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) { - $docSheet->setShowSummaryBelow(false); - } else { - $docSheet->setShowSummaryBelow(true); - } - } - - if (isset($xmlSheet->sheetFormatPr)) { - if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { - $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); - } - if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { - $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); - } - } - - if (isset($xmlSheet->cols) && !$this->_readDataOnly) { - foreach ($xmlSheet->cols->col as $col) { - for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { - if ($col["bestFit"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); - } - if ($col["hidden"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); - } - if ($col["collapsed"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true); - } - if ($col["outlineLevel"] > 0) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); - } - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); - - if (intval($col["max"]) == 16384) { - break; + + if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { + if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { + $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); + } + + if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { + $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); + } + + if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { + $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false); + } + + if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { + $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false); + } + + if (isset($xmlSheet->sheetViews->sheetView->pane)) { + if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { + $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); + } else { + $xSplit = 0; + $ySplit = 0; + + if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { + $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); + } + + if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { + $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); + } + + $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); + } + } + + if (isset($xmlSheet->sheetViews->sheetView->selection)) { + if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { + $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; + $sqref = explode(' ', $sqref); + $sqref = $sqref[0]; + $docSheet->setSelectedCells($sqref); } } + } - } - - if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { - if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') { - $docSheet->setShowGridlines(true); - } - - if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') { - $docSheet->setPrintGridlines(true); - } - - if ($xmlSheet->printOptions['horizontalCentered']) { - $docSheet->getPageSetup()->setHorizontalCentered(true); - } - if ($xmlSheet->printOptions['verticalCentered']) { - $docSheet->getPageSetup()->setVerticalCentered(true); - } - } - - if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { - foreach ($xmlSheet->sheetData->row as $row) { - if ($row["ht"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); - } - if ($row["hidden"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setVisible(false); - } - if ($row["collapsed"]) { - $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true); - } - if ($row["outlineLevel"] > 0) { - $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); - } - - foreach ($row->c as $c) { - $r = (string) $c["r"]; - $cellDataType = (string) $c["t"]; - $value = null; - $calculatedValue = null; - - // Read cell? - if (!is_null($this->getReadFilter())) { - $coordinates = PHPExcel_Cell::coordinateFromString($r); - - if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { - break; - } - } - -// echo 'Reading cell '.$coordinates[0].$coordinates[1].'
'; -// print_r($c); -// echo '
'; -// echo 'Cell Data Type is '.$cellDataType.': '; -// - // Read cell! - switch ($cellDataType) { - case "s": -// echo 'String
'; - if ((string)$c->v != '') { - $value = $sharedStrings[intval($c->v)]; - - if ($value instanceof PHPExcel_RichText) { - $value = clone $value; - } - } else { - $value = ''; - } - - break; - case "b": -// echo 'Boolean
'; - if (!isset($c->f)) { - $value = $this->_castToBool($c); - } else { - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); -// echo '$calculatedValue = '.$calculatedValue.'
'; - } - break; - case "inlineStr": -// echo 'Inline String
'; - $value = $this->_parseRichText($c->is); - - break; - case "e": -// echo 'Error
'; - if (!isset($c->f)) { - $value = $this->_castToError($c); - } else { - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); -// echo '$calculatedValue = '.$calculatedValue.'
'; - } - - break; - - default: -// echo 'Default
'; - if (!isset($c->f)) { -// echo 'Not a Formula
'; - $value = $this->_castToString($c); - } else { -// echo 'Treat as Formula
'; - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); -// echo '$calculatedValue = '.$calculatedValue.'
'; - } - - break; - } -// echo 'Value is '.$value.'
'; - - // Check for numeric values - if (is_numeric($value) && $cellDataType != 's') { - if ($value == (int)$value) $value = (int)$value; - elseif ($value == (float)$value) $value = (float)$value; - elseif ($value == (double)$value) $value = (double)$value; - } - - // Rich text? - if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { - $value = $value->getPlainText(); - } - - // Assign value - if ($cellDataType != '') { - $docSheet->setCellValueExplicit($r, $value, $cellDataType); - } else { - $docSheet->setCellValue($r, $value); - } - if (!is_null($calculatedValue)) { - $docSheet->getCell($r)->setCalculatedValue($calculatedValue); - } - - // Style information? - if ($c["s"] && !$this->_readDataOnly) { - // no style index means 0, it seems - $docSheet->getCell($r)->setXfIndex(isset($styles[intval($c["s"])]) ? - intval($c["s"]) : 0); - } - - // Set rich text parent - if ($value instanceof PHPExcel_RichText && !$this->_readDataOnly) { - $value->setParent($docSheet->getCell($r)); - } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { + if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { + $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); } } - } - - $conditionals = array(); - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { - foreach ($xmlSheet->conditionalFormatting as $conditional) { - foreach ($conditional->cfRule as $cfRule) { - if ( - ( - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - ) && isset($dxfs[intval($cfRule["dxfId"])]) - ) { - $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; - } - } - } - - foreach ($conditionals as $ref => $cfRules) { - ksort($cfRules); - $conditionalStyles = array(); - foreach ($cfRules as $cfRule) { - $objConditional = new PHPExcel_Style_Conditional(); - $objConditional->setConditionType((string)$cfRule["type"]); - $objConditional->setOperatorType((string)$cfRule["operator"]); - - if ((string)$cfRule["text"] != '') { - $objConditional->setText((string)$cfRule["text"]); - } - - if (count($cfRule->formula) > 1) { - foreach ($cfRule->formula as $formula) { - $objConditional->addCondition((string)$formula); - } - } else { - $objConditional->addCondition((string)$cfRule->formula); - } - $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); - $conditionalStyles[] = $objConditional; - } - - // Extract all cell references in $ref - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); - foreach ($aReferences as $reference) { - $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); - } - } - } - - $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - foreach ($aKeys as $key) { - $method = "set" . ucfirst($key); - $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true"); - } - } - - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); - if ($xmlSheet->protectedRanges->protectedRange) { - foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { - $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); - } - } - } - - if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { - $docSheet->setAutoFilter((string) $xmlSheet->autoFilter["ref"]); - } - - if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { - foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { - $docSheet->mergeCells((string) $mergeCell["ref"]); - } - } - - if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { - $docPageMargins = $docSheet->getPageMargins(); - $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); - $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); - $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); - $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); - $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); - $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); - } - - if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { - $docPageSetup = $docSheet->getPageSetup(); - - if (isset($xmlSheet->pageSetup["orientation"])) { - $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); - } - if (isset($xmlSheet->pageSetup["paperSize"])) { - $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); - } - if (isset($xmlSheet->pageSetup["scale"])) { - $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"])); - } - if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) > 0) { - $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"])); - } - if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) > 0) { - $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"])); - } - } - - if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { - $docHeaderFooter = $docSheet->getHeaderFooter(); - - if (isset($xmlSheet->headerFooter["differentOddEven"]) && - ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) { - $docHeaderFooter->setDifferentOddEven(true); - } else { - $docHeaderFooter->setDifferentOddEven(false); - } - if (isset($xmlSheet->headerFooter["differentFirst"]) && - ((string)$xmlSheet->headerFooter["differentFirst"] == 'true' || (string)$xmlSheet->headerFooter["differentFirst"] == '1')) { - $docHeaderFooter->setDifferentFirst(true); - } else { - $docHeaderFooter->setDifferentFirst(false); - } - if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && - ((string)$xmlSheet->headerFooter["scaleWithDoc"] == 'false' || (string)$xmlSheet->headerFooter["scaleWithDoc"] == '0')) { - $docHeaderFooter->setScaleWithDocument(false); - } else { - $docHeaderFooter->setScaleWithDocument(true); - } - if (isset($xmlSheet->headerFooter["alignWithMargins"]) && - ((string)$xmlSheet->headerFooter["alignWithMargins"] == 'false' || (string)$xmlSheet->headerFooter["alignWithMargins"] == '0')) { - $docHeaderFooter->setAlignWithMargins(false); - } else { - $docHeaderFooter->setAlignWithMargins(true); - } - - $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); - $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); - $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); - $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); - $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); - $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); - } - - if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { - foreach ($xmlSheet->rowBreaks->brk as $brk) { - if ($brk["man"]) { - $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); - } - } - } - if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { - foreach ($xmlSheet->colBreaks->brk as $brk) { - if ($brk["man"]) { - $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex($brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); - } - } - } - - if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { - foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { - // Uppercase coordinate - $range = strtoupper($dataValidation["sqref"]); - - // Extract all cell references in $range - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($range); - foreach ($aReferences as $reference) { - // Create validation - $docValidation = $docSheet->getCell($reference)->getDataValidation(); - $docValidation->setType((string) $dataValidation["type"]); - $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); - $docValidation->setOperator((string) $dataValidation["operator"]); - $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); - $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); - $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); - $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); - $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); - $docValidation->setError((string) $dataValidation["error"]); - $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); - $docValidation->setPrompt((string) $dataValidation["prompt"]); - $docValidation->setFormula1((string) $dataValidation->formula1); - $docValidation->setFormula2((string) $dataValidation->formula2); - } - } - } - - // Add hyperlinks - $hyperlinks = array(); - if (!$this->_readDataOnly) { - // Locate hyperlink relations - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { - $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; - } - } - } - - // Loop trough hyperlinks - if ($xmlSheet && $xmlSheet->hyperlinks) { - foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { - // Link url - $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { - if (isset($linkRel['id'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); - } - if (isset($hyperlink['location'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); - } - - // Tooltip - if (isset($hyperlink['tooltip'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); - } - } - } - } - } - - // Add comments - $comments = array(); - $vmlComments = array(); - if (!$this->_readDataOnly) { - // Locate comment relations - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { - $comments[(string)$ele["Id"]] = (string)$ele["Target"]; - } - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { - $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; - } - } - } - - // Loop trough comments - foreach ($comments as $relName => $relPath) { - // Load comments file - $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $commentsFile = simplexml_load_string($zip->getFromName($relPath) ); - - // Utility variables - $authors = array(); - - // Loop trough authors - foreach ($commentsFile->authors->author as $author) { - $authors[] = (string)$author; - } - - // Loop trough contents - foreach ($commentsFile->commentList->comment as $comment) { - $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); - $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); - } - } - - // Loop trough VML comments - foreach ($vmlComments as $relName => $relPath) { - // Load VML comments file - $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $vmlCommentsFile = simplexml_load_string( $zip->getFromName($relPath) ); - $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - - $shapes = $vmlCommentsFile->xpath('//v:shape'); - foreach ($shapes as $shape) { - $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - - if (isset($shape['style'])) { - $style = (string)$shape['style']; - $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); - $column = null; - $row = null; - - $clientData = $shape->xpath('.//x:ClientData'); - if (is_array($clientData)) { - $clientData = $clientData[0]; - - if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { - $temp = $clientData->xpath('.//x:Row'); - if (is_array($temp)) $row = $temp[0]; - - $temp = $clientData->xpath('.//x:Column'); - if (is_array($temp)) $column = $temp[0]; - } - } - - if (!is_null($column) && !is_null($row)) { - // Set comment properties - $comment = $docSheet->getCommentByColumnAndRow($column, $row + 1); - $comment->getFillColor()->setRGB( $fillColor ); - - // Parse style - $styleArray = explode(';', str_replace(' ', '', $style)); - foreach ($styleArray as $stylePair) { - $stylePair = explode(':', $stylePair); - - if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); - if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); - if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); - if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); - if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); - - } - } - } - } - } - - // Header/footer images - if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $vmlRelationship = ''; - - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { - $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); - } - } - - if ($vmlRelationship != '') { - // Fetch linked images - $relsVML = simplexml_load_string($zip->getFromName( dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $drawings = array(); - foreach ($relsVML->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { - $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); - } - } - - // Fetch VML document - $vmlDrawing = simplexml_load_string($zip->getFromName($vmlRelationship)); - $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - - $hfImages = array(); - - $shapes = $vmlDrawing->xpath('//v:shape'); - foreach ($shapes as $shape) { - $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - $imageData = $shape->xpath('//v:imagedata'); - $imageData = $imageData[0]; - - $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); - $style = self::toCSSArray( (string)$shape['style'] ); - - $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); - if (isset($imageData['title'])) { - $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); - } - - $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false); - $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); - $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); - $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); - $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); - $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); - $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); - } - - $docSheet->getHeaderFooter()->setImages($hfImages); - } - } - } - - } - -// TODO: Make sure drawings and graph are loaded differently! - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $drawings = array(); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { - $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); - } - } - if ($xmlSheet->drawing && !$this->_readDataOnly) { - foreach ($xmlSheet->drawing as $drawing) { - $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $relsDrawing = simplexml_load_string($zip->getFromName( dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $images = array(); - - if ($relsDrawing && $relsDrawing->Relationship) { - foreach ($relsDrawing->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { - $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); - } - } - } - $xmlDrawing = simplexml_load_string($zip->getFromName($fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); - - if ($xmlDrawing->oneCellAnchor) { - foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { - if ($oneCellAnchor->pic->blipFill) { - $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; - $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; - $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; - $objDrawing = new PHPExcel_Worksheet_Drawing; - $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); - $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); - $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); - $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); - $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); - $objDrawing->setResizeProportional(false); - $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); - $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); - if ($xfrm) { - $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); - } - if ($outerShdw) { - $shadow = $objDrawing->getShadow(); - $shadow->setVisible(true); - $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); - $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); - $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); - $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); - $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); - $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); - } - $objDrawing->setWorksheet($docSheet); - } - } - } - if ($xmlDrawing->twoCellAnchor) { - foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { - if ($twoCellAnchor->pic->blipFill) { - $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; - $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; - $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; - $objDrawing = new PHPExcel_Worksheet_Drawing; - $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); - $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); - $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); - $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); - $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); - $objDrawing->setResizeProportional(false); - - $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); - $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); - - if ($xfrm) { - $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); - } - if ($outerShdw) { - $shadow = $objDrawing->getShadow(); - $shadow->setVisible(true); - $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); - $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); - $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); - $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); - $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); - $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); - } - $objDrawing->setWorksheet($docSheet); - } - } - } - - } - } - } - - // Loop trough definedNames - if ($xmlWorkbook->definedNames) { - foreach ($xmlWorkbook->definedNames->definedName as $definedName) { - // Extract range - $extractedRange = (string)$definedName; - $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); - $extractedRange = str_replace('$', '', $extractedRange); - - // Valid range? - if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { - continue; - } - - // Some definedNames are only applicable if we are on the same sheet... - if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { - // Switch on type - switch ((string)$definedName['name']) { - - case '_xlnm._FilterDatabase': - $docSheet->setAutoFilter($extractedRange); - break; - - case '_xlnm.Print_Titles': - // Split $extractedRange - $extractedRange = explode(',', $extractedRange); - - // Set print titles - if (isset($extractedRange[0])) { - $range = explode(':', $extractedRange[0]); - - if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') - $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); - $range[0] = str_replace('$', '', $range[0]); - if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') - $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); - $range[1] = str_replace('$', '', $range[1]); - - $docSheet->getPageSetup()->setColumnsToRepeatAtLeft( $range ); - } - if (isset($extractedRange[1])) { - $range = explode(':', $extractedRange[1]); - - if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') - $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); - $range[0] = str_replace('$', '', $range[0]); - if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') - $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); - $range[1] = str_replace('$', '', $range[1]); - - $docSheet->getPageSetup()->setRowsToRepeatAtTop( $range ); - } - - break; - - case '_xlnm.Print_Area': - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - - $docSheet->getPageSetup()->setPrintArea($extractedRange); - break; - - default: - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, true) ); - break; - } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { + if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) { + $docSheet->setShowSummaryRight(false); } else { - // "Global" definedNames - $locatedSheet = null; - $extractedSheetName = ''; - if (strpos( (string)$definedName, '!' ) !== false) { - // Extract sheet name - $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); - $extractedSheetName = $extractedSheetName[0]; - - // Locate sheet - $locatedSheet = $excel->getSheetByName($extractedSheetName); - - // Modify range - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - } - - if (!is_null($locatedSheet)) { - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + $docSheet->setShowSummaryRight(true); + } + + if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) { + $docSheet->setShowSummaryBelow(false); + } else { + $docSheet->setShowSummaryBelow(true); + } + } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { + if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && $xmlSheet->sheetPr->pageSetUpPr['fitToPage'] == false) { + $docSheet->getPageSetup()->setFitToPage(false); + } else { + $docSheet->getPageSetup()->setFitToPage(true); + } + } + + if (isset($xmlSheet->sheetFormatPr)) { + if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { + $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); + } + if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { + $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); + } + } + + if (isset($xmlSheet->cols) && !$this->_readDataOnly) { + foreach ($xmlSheet->cols->col as $col) { + for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { + if ($col["style"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); + } + if ($col["bestFit"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); + } + if ($col["hidden"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); + } + if ($col["collapsed"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true); + } + if ($col["outlineLevel"] > 0) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); + } + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); + + if (intval($col["max"]) == 16384) { + break; + } } } } + + if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { + if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') { + $docSheet->setShowGridlines(true); + } + + if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') { + $docSheet->setPrintGridlines(true); + } + + if ($xmlSheet->printOptions['horizontalCentered']) { + $docSheet->getPageSetup()->setHorizontalCentered(true); + } + if ($xmlSheet->printOptions['verticalCentered']) { + $docSheet->getPageSetup()->setVerticalCentered(true); + } + } + + if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { + foreach ($xmlSheet->sheetData->row as $row) { + if ($row["ht"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); + } + if ($row["hidden"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setVisible(false); + } + if ($row["collapsed"]) { + $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true); + } + if ($row["outlineLevel"] > 0) { + $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); + } + if ($row["s"]) { + $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); + } + + foreach ($row->c as $c) { + $r = (string) $c["r"]; + $cellDataType = (string) $c["t"]; + $value = null; + $calculatedValue = null; + + // Read cell? + if (!is_null($this->getReadFilter())) { + $coordinates = PHPExcel_Cell::coordinateFromString($r); + + if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { + continue; + } + } + + // echo 'Reading cell '.$coordinates[0].$coordinates[1].'
'; + // print_r($c); + // echo '
'; + // echo 'Cell Data Type is '.$cellDataType.': '; + // + // Read cell! + switch ($cellDataType) { + case "s": + // echo 'String
'; + if ((string)$c->v != '') { + $value = $sharedStrings[intval($c->v)]; + + if ($value instanceof PHPExcel_RichText) { + $value = clone $value; + } + } else { + $value = ''; + } + + break; + case "b": + // echo 'Boolean
'; + if (!isset($c->f)) { + $value = $this->_castToBool($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); + // echo '$calculatedValue = '.$calculatedValue.'
'; + } + break; + case "inlineStr": + // echo 'Inline String
'; + $value = $this->_parseRichText($c->is); + + break; + case "e": + // echo 'Error
'; + if (!isset($c->f)) { + $value = $this->_castToError($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); + // echo '$calculatedValue = '.$calculatedValue.'
'; + } + + break; + + default: + // echo 'Default
'; + if (!isset($c->f)) { + // echo 'Not a Formula
'; + $value = $this->_castToString($c); + } else { + // echo 'Treat as Formula
'; + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); + // echo '$calculatedValue = '.$calculatedValue.'
'; + } + + break; + } + // echo 'Value is '.$value.'
'; + + // Check for numeric values + if (is_numeric($value) && $cellDataType != 's') { + if ($value == (int)$value) $value = (int)$value; + elseif ($value == (float)$value) $value = (float)$value; + elseif ($value == (double)$value) $value = (double)$value; + } + + // Rich text? + if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { + $value = $value->getPlainText(); + } + + // Assign value + if ($cellDataType != '') { + $docSheet->setCellValueExplicit($r, $value, $cellDataType); + } else { + $docSheet->setCellValue($r, $value); + } + if (!is_null($calculatedValue)) { + $docSheet->getCell($r)->setCalculatedValue($calculatedValue); + } + + // Style information? + if ($c["s"] && !$this->_readDataOnly) { + // no style index means 0, it seems + $docSheet->getCell($r)->setXfIndex(isset($styles[intval($c["s"])]) ? + intval($c["s"]) : 0); + } + + // Set rich text parent + if ($value instanceof PHPExcel_RichText && !$this->_readDataOnly) { + $value->setParent($docSheet->getCell($r)); + } + } + } + } + + $conditionals = array(); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { + foreach ($xmlSheet->conditionalFormatting as $conditional) { + foreach ($conditional->cfRule as $cfRule) { + if ( + ( + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + ) && isset($dxfs[intval($cfRule["dxfId"])]) + ) { + $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; + } + } + } + + foreach ($conditionals as $ref => $cfRules) { + ksort($cfRules); + $conditionalStyles = array(); + foreach ($cfRules as $cfRule) { + $objConditional = new PHPExcel_Style_Conditional(); + $objConditional->setConditionType((string)$cfRule["type"]); + $objConditional->setOperatorType((string)$cfRule["operator"]); + + if ((string)$cfRule["text"] != '') { + $objConditional->setText((string)$cfRule["text"]); + } + + if (count($cfRule->formula) > 1) { + foreach ($cfRule->formula as $formula) { + $objConditional->addCondition((string)$formula); + } + } else { + $objConditional->addCondition((string)$cfRule->formula); + } + $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); + $conditionalStyles[] = $objConditional; + } + + // Extract all cell references in $ref + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); + foreach ($aReferences as $reference) { + $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); + } + } + } + + $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + foreach ($aKeys as $key) { + $method = "set" . ucfirst($key); + $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true"); + } + } + + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); + if ($xmlSheet->protectedRanges->protectedRange) { + foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { + $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); + } + } + } + + if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { + $docSheet->setAutoFilter((string) $xmlSheet->autoFilter["ref"]); + } + + if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { + foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { + $docSheet->mergeCells((string) $mergeCell["ref"]); + } + } + + if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { + $docPageMargins = $docSheet->getPageMargins(); + $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); + $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); + $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); + $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); + $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); + $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); + } + + if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { + $docPageSetup = $docSheet->getPageSetup(); + + if (isset($xmlSheet->pageSetup["orientation"])) { + $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); + } + if (isset($xmlSheet->pageSetup["paperSize"])) { + $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); + } + if (isset($xmlSheet->pageSetup["scale"])) { + $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), false); + } + if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { + $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), false); + } + if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { + $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), false); + } + if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && + ((string)$xmlSheet->pageSetup["useFirstPageNumber"] == 'true' || (string)$xmlSheet->pageSetup["useFirstPageNumber"] == '1')) { + $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); + } + } + + if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { + $docHeaderFooter = $docSheet->getHeaderFooter(); + + if (isset($xmlSheet->headerFooter["differentOddEven"]) && + ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) { + $docHeaderFooter->setDifferentOddEven(true); + } else { + $docHeaderFooter->setDifferentOddEven(false); + } + if (isset($xmlSheet->headerFooter["differentFirst"]) && + ((string)$xmlSheet->headerFooter["differentFirst"] == 'true' || (string)$xmlSheet->headerFooter["differentFirst"] == '1')) { + $docHeaderFooter->setDifferentFirst(true); + } else { + $docHeaderFooter->setDifferentFirst(false); + } + if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && + ((string)$xmlSheet->headerFooter["scaleWithDoc"] == 'false' || (string)$xmlSheet->headerFooter["scaleWithDoc"] == '0')) { + $docHeaderFooter->setScaleWithDocument(false); + } else { + $docHeaderFooter->setScaleWithDocument(true); + } + if (isset($xmlSheet->headerFooter["alignWithMargins"]) && + ((string)$xmlSheet->headerFooter["alignWithMargins"] == 'false' || (string)$xmlSheet->headerFooter["alignWithMargins"] == '0')) { + $docHeaderFooter->setAlignWithMargins(false); + } else { + $docHeaderFooter->setAlignWithMargins(true); + } + + $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); + $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); + $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); + $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); + $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); + $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); + } + + if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->rowBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); + } + } + } + if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->colBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex($brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); + } + } + } + + if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { + foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { + // Uppercase coordinate + $range = strtoupper($dataValidation["sqref"]); + + // Extract all cell references in $range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($range); + foreach ($aReferences as $reference) { + // Create validation + $docValidation = $docSheet->getCell($reference)->getDataValidation(); + $docValidation->setType((string) $dataValidation["type"]); + $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); + $docValidation->setOperator((string) $dataValidation["operator"]); + $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); + $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); + $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); + $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); + $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); + $docValidation->setError((string) $dataValidation["error"]); + $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); + $docValidation->setPrompt((string) $dataValidation["prompt"]); + $docValidation->setFormula1((string) $dataValidation->formula1); + $docValidation->setFormula2((string) $dataValidation->formula2); + } + } + } + + // Add hyperlinks + $hyperlinks = array(); + if (!$this->_readDataOnly) { + // Locate hyperlink relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { + $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } + + // Loop through hyperlinks + if ($xmlSheet && $xmlSheet->hyperlinks) { + foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { + // Link url + $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { + if (isset($linkRel['id'])) { + $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); + } + if (isset($hyperlink['location'])) { + $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); + } + + // Tooltip + if (isset($hyperlink['tooltip'])) { + $docSheet->getCell( $cellReference )->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); + } + } + } + } + } + + // Add comments + $comments = array(); + $vmlComments = array(); + if (!$this->_readDataOnly) { + // Locate comment relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { + $comments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } + + // Loop through comments + foreach ($comments as $relName => $relPath) { + // Load comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $commentsFile = simplexml_load_string($this->_getFromZipArchive($zip, $relPath) ); + + // Utility variables + $authors = array(); + + // Loop through authors + foreach ($commentsFile->authors->author as $author) { + $authors[] = (string)$author; + } + + // Loop through contents + foreach ($commentsFile->commentList->comment as $comment) { + $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); + $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); + } + } + + // Loop through VML comments + foreach ($vmlComments as $relName => $relPath) { + // Load VML comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $vmlCommentsFile = simplexml_load_string( $this->_getFromZipArchive($zip, $relPath) ); + $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + $shapes = $vmlCommentsFile->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + if (isset($shape['style'])) { + $style = (string)$shape['style']; + $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); + $column = null; + $row = null; + + $clientData = $shape->xpath('.//x:ClientData'); + if (is_array($clientData)) { + $clientData = $clientData[0]; + + if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { + $temp = $clientData->xpath('.//x:Row'); + if (is_array($temp)) $row = $temp[0]; + + $temp = $clientData->xpath('.//x:Column'); + if (is_array($temp)) $column = $temp[0]; + } + } + + if (!is_null($column) && !is_null($row)) { + // Set comment properties + $comment = $docSheet->getCommentByColumnAndRow($column, $row + 1); + $comment->getFillColor()->setRGB( $fillColor ); + + // Parse style + $styleArray = explode(';', str_replace(' ', '', $style)); + foreach ($styleArray as $stylePair) { + $stylePair = explode(':', $stylePair); + + if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); + if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); + if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); + if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); + if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); + + } + } + } + } + } + + // Header/footer images + if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $vmlRelationship = ''; + + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + + if ($vmlRelationship != '') { + // Fetch linked images + $relsVML = simplexml_load_string($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsVML->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); + } + } + + // Fetch VML document + $vmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $vmlRelationship)); + $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + $hfImages = array(); + + $shapes = $vmlDrawing->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + $imageData = $shape->xpath('//v:imagedata'); + $imageData = $imageData[0]; + + $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); + $style = self::toCSSArray( (string)$shape['style'] ); + + $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); + if (isset($imageData['title'])) { + $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); + } + + $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); + $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); + $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); + $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); + $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); + } + + $docSheet->getHeaderFooter()->setImages($hfImages); + } + } + } + + } + + // TODO: Make sure drawings and graph are loaded differently! + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { + $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + if ($xmlSheet->drawing && !$this->_readDataOnly) { + foreach ($xmlSheet->drawing as $drawing) { + $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $relsDrawing = simplexml_load_string($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $images = array(); + + if ($relsDrawing && $relsDrawing->Relationship) { + foreach ($relsDrawing->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); + } + } + } + $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); + + if ($xmlDrawing->oneCellAnchor) { + foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { + if ($oneCellAnchor->pic->blipFill) { + $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } + } + } + if ($xmlDrawing->twoCellAnchor) { + foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { + if ($twoCellAnchor->pic->blipFill) { + $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); + + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } + } + } + + } + } + } + + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + $extractedRange = str_replace('$', '', $extractedRange); + + // Valid range? + if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { + continue; + } + + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { + // Switch on type + switch ((string)$definedName['name']) { + + case '_xlnm._FilterDatabase': + $docSheet->setAutoFilter($extractedRange); + break; + + case '_xlnm.Print_Titles': + // Split $extractedRange + $extractedRange = explode(',', $extractedRange); + + // Set print titles + if (isset($extractedRange[0])) { + $range = explode(':', $extractedRange[0]); + + if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') + $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); + $range[0] = str_replace('$', '', $range[0]); + if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') + $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); + $range[1] = str_replace('$', '', $range[1]); + + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft( $range ); + } + if (isset($extractedRange[1])) { + $range = explode(':', $extractedRange[1]); + + if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') + $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); + $range[0] = str_replace('$', '', $range[0]); + if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') + $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); + $range[1] = str_replace('$', '', $range[1]); + + $docSheet->getPageSetup()->setRowsToRepeatAtTop( $range ); + } + + break; + + case '_xlnm.Print_Area': + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + + $docSheet->getPageSetup()->setPrintArea($extractedRange); + break; + + default: + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, true) ); + break; + } + } else { + // "Global" definedNames + $locatedSheet = null; + $extractedSheetName = ''; + if (strpos( (string)$definedName, '!' ) !== false) { + // Extract sheet name + $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); + $extractedSheetName = $extractedSheetName[0]; + + // Locate sheet + $locatedSheet = $excel->getSheetByName($extractedSheetName); + + // Modify range + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + } + + if (!is_null($locatedSheet)) { + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + } + } + } + } + + // Next sheet id + ++$sheetId; } - - // Next sheet id - ++$sheetId; } if (!$this->_readDataOnly) { @@ -1322,9 +1373,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index // keep active sheet index if sheet is still loaded, else first sheet is set as the active - if ($mapSheetId[$activeTab] !== null) { + if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) { $excel->setActiveSheetIndex($mapSheetId[$activeTab]); } else { + if ($excel->getSheetCount() == 0) + { + $excel->createSheet(); + } $excel->setActiveSheetIndex(0); } } @@ -1346,7 +1401,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader private function _readStyle($docStyle, $style) { // format code - if ($style->applyNumberFormat) $docStyle->getNumberFormat()->setFormatCode($style->numFmt); + if (isset($style->numFmt)) { + $docStyle->getNumberFormat()->setFormatCode($style->numFmt); + } // font if (isset($style->font)) { @@ -1381,7 +1438,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // fill - if (isset($style->fill) && ($style->applyFill || $style instanceof SimpleXMLElement)) { + if (isset($style->fill)) { if ($style->fill->gradientFill) { $gradientFill = $style->fill->gradientFill[0]; $docStyle->getFill()->setFillType((string) $gradientFill["type"]); @@ -1404,11 +1461,23 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // border - if (isset($style->border) && ($style->applyBorder || $style instanceof SimpleXMLElement)) { - if ($style->border["diagonalUp"] == 'true') { + if (isset($style->border)) { + $diagonalUp = false; + $diagonalDown = false; + if ($style->border["diagonalUp"] == 'true' || $style->border["diagonalUp"] == 1) { + $diagonalUp = true; + } + if ($style->border["diagonalDown"] == 'true' || $style->border["diagonalDown"] == 1) { + $diagonalDown = true; + } + if ($diagonalUp == false && $diagonalDown == false) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp == true && $diagonalDown == false) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); - } elseif ($style->border["diagonalDown"] == 'true') { + } elseif ($diagonalUp == false && $diagonalDown == true) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } elseif ($diagonalUp == true && $diagonalDown == true) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); } $this->_readBorder($docStyle->getBorders()->getLeft(), $style->border->left); $this->_readBorder($docStyle->getBorders()->getRight(), $style->border->right); @@ -1418,7 +1487,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // alignment - if (isset($style->alignment) && ($style->applyAlignment || $style instanceof SimpleXMLElement)) { + if (isset($style->alignment)) { $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]); $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]); @@ -1436,7 +1505,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // protection - if (isset($style->protection) && $style->applyProtection) { + if (isset($style->protection)) { if (isset($style->protection['locked'])) { if ((string)$style->protection['locked'] == 'true') { $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel5.php b/libraries/PHPExcel/PHPExcel/Reader/Excel5.php index 0dcaa2941..8509b0801 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of ParseXL (used as the base for this class): @@ -107,6 +107,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; /** PHPExcel_Worksheet_MemoryDrawing */ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; +/** PHPExcel_Style_Borders */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php'; + /** * PHPExcel_Reader_Excel5 @@ -115,7 +118,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader { @@ -129,6 +132,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_FORMULA = 0x0006; const XLS_Type_EOF = 0x000a; const XLS_Type_PROTECT = 0x0012; + const XLS_Type_OBJECTPROTECT = 0x0063; + const XLS_Type_SCENPROTECT = 0x00dd; const XLS_Type_PASSWORD = 0x0013; const XLS_Type_HEADER = 0x0014; const XLS_Type_FOOTER = 0x0015; @@ -137,6 +142,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_VERTICALPAGEBREAKS = 0x001a; const XLS_Type_HORIZONTALPAGEBREAKS = 0x001b; const XLS_Type_NOTE = 0x001c; + const XLS_Type_SELECTION = 0x001d; const XLS_Type_DATEMODE = 0x0022; const XLS_Type_LEFTMARGIN = 0x0026; const XLS_Type_RIGHTMARGIN = 0x0027; @@ -188,7 +194,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_FORMAT = 0x041e; const XLS_Type_SHAREDFMLA = 0x04bc; const XLS_Type_BOF = 0x0809; + const XLS_Type_SHEETPROTECTION = 0x0867; const XLS_Type_RANGEPROTECTION = 0x0868; + const XLS_Type_SHEETLAYOUT = 0x0862; + const XLS_Type_XFEXT = 0x087d; const XLS_Type_UNKNOWN = 0xffff; /** @@ -578,6 +587,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_FONT: $this->_readFont(); break; case self::XLS_Type_FORMAT: $this->_readFormat(); break; case self::XLS_Type_XF: $this->_readXf(); break; + case self::XLS_Type_XFEXT: $this->_readXfExt(); break; case self::XLS_Type_STYLE: $this->_readStyle(); break; case self::XLS_Type_PALETTE: $this->_readPalette(); break; case self::XLS_Type_SHEET: $this->_readSheet(); break; @@ -595,30 +605,57 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Cannot be resolved already in XF record, because PALETTE record comes afterwards if (!$this->_readDataOnly) { foreach ($this->_objFonts as $objFont) { - $color = $this->_readColor($objFont->colorIndex); - $objFont->getColor()->setRGB($color['rgb']); + if (isset($objFont->colorIndex)) { + $color = $this->_readColor($objFont->colorIndex); + $objFont->getColor()->setRGB($color['rgb']); + } } foreach ($this->_phpExcel->getCellXfCollection() as $objStyle) { // fill start and end color - $startColor = $this->_readColor($objStyle->getFill()->startcolorIndex); - $objStyle->getFill()->getStartColor()->setRGB($startColor['rgb']); + $fill = $objStyle->getFill(); - $endColor = $this->_readColor($objStyle->getFill()->endcolorIndex); - $objStyle->getFill()->getEndColor()->setRGB($endColor['rgb']); + if (isset($fill->startcolorIndex)) { + $startColor = $this->_readColor($fill->startcolorIndex); + $fill->getStartColor()->setRGB($startColor['rgb']); + } + + if (isset($fill->endcolorIndex)) { + $endColor = $this->_readColor($fill->endcolorIndex); + $fill->getEndColor()->setRGB($endColor['rgb']); + } // border colors - $borderTopColor = $this->_readColor($objStyle->getBorders()->getTop()->colorIndex); - $objStyle->getBorders()->getTop()->getColor()->setRGB($borderTopColor['rgb']); + $top = $objStyle->getBorders()->getTop(); + $right = $objStyle->getBorders()->getRight(); + $bottom = $objStyle->getBorders()->getBottom(); + $left = $objStyle->getBorders()->getLeft(); + $diagonal = $objStyle->getBorders()->getDiagonal(); - $borderRightColor = $this->_readColor($objStyle->getBorders()->getRight()->colorIndex); - $objStyle->getBorders()->getRight()->getColor()->setRGB($borderRightColor['rgb']); + if (isset($top->colorIndex)) { + $borderTopColor = $this->_readColor($top->colorIndex); + $top->getColor()->setRGB($borderTopColor['rgb']); + } - $borderBottomColor = $this->_readColor($objStyle->getBorders()->getBottom()->colorIndex); - $objStyle->getBorders()->getBottom()->getColor()->setRGB($borderBottomColor['rgb']); + if (isset($right->colorIndex)) { + $borderRightColor = $this->_readColor($right->colorIndex); + $right->getColor()->setRGB($borderRightColor['rgb']); + } - $borderLeftColor = $this->_readColor($objStyle->getBorders()->getLeft()->colorIndex); - $objStyle->getBorders()->getLeft()->getColor()->setRGB($borderLeftColor['rgb']); + if (isset($bottom->colorIndex)) { + $borderBottomColor = $this->_readColor($bottom->colorIndex); + $bottom->getColor()->setRGB($borderBottomColor['rgb']); + } + + if (isset($left->colorIndex)) { + $borderLeftColor = $this->_readColor($left->colorIndex); + $left->getColor()->setRGB($borderLeftColor['rgb']); + } + + if (isset($diagonal->colorIndex)) { + $borderDiagonalColor = $this->_readColor($diagonal->colorIndex); + $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); + } } } @@ -644,6 +681,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add sheet to PHPExcel object $this->_phpSheet = $this->_phpExcel->createSheet(); $this->_phpSheet->setTitle($sheet['name']); + $this->_phpSheet->setSheetState($sheet['sheetState']); $this->_pos = $sheet['offset']; @@ -698,6 +736,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_BOTTOMMARGIN: $this->_readBottomMargin(); break; case self::XLS_Type_PAGESETUP: $this->_readPageSetup(); break; case self::XLS_Type_PROTECT: $this->_readProtect(); break; + case self::XLS_Type_SCENPROTECT: $this->_readScenProtect(); break; + case self::XLS_Type_OBJECTPROTECT: $this->_readObjectProtect(); break; case self::XLS_Type_PASSWORD: $this->_readPassword(); break; case self::XLS_Type_DEFCOLWIDTH: $this->_readDefColWidth(); break; case self::XLS_Type_COLINFO: $this->_readColInfo(); break; @@ -719,8 +759,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_WINDOW2: $this->_readWindow2(); break; case self::XLS_Type_SCL: $this->_readScl(); break; case self::XLS_Type_PANE: $this->_readPane(); break; + case self::XLS_Type_SELECTION: $this->_readSelection(); break; case self::XLS_Type_MERGEDCELLS: $this->_readMergedCells(); break; case self::XLS_Type_HYPERLINK: $this->_readHyperLink(); break; + case self::XLS_Type_SHEETLAYOUT: $this->_readSheetLayout(); break; + case self::XLS_Type_SHEETPROTECTION: $this->_readSheetProtection(); break; case self::XLS_Type_RANGEPROTECTION: $this->_readRangeProtection(); break; //case self::XLS_Type_IMDATA: $this->_readImData(); break; case self::XLS_Type_CONTINUE: $this->_readContinue(); break; @@ -841,21 +884,22 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? + $extractedRanges = array(); foreach ($ranges as $range) { - // $range should look like this one of these + // $range should look like one of these // Foo!$C$7:$J$66 // Bar!$A$1:$IV$2 $explodes = explode('!', $range); + $sheetName = $explodes[0]; if (count($explodes) == 2) { - if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) { - $extractedRange = $explodes[1]; - $extractedRange = str_replace('$', '', $extractedRange); - $docSheet->getPageSetup()->setPrintArea($extractedRange); - } + $extractedRanges[] = str_replace('$', '', $explodes[1]); // C7:J66 } } + if ($docSheet = $this->_phpExcel->getSheetByName($sheetName)) { + $docSheet->getPageSetup()->setPrintArea(implode(',', $extractedRanges)); // C7:J66,A1:IV2 + } break; case pack('C', 0x07): @@ -1185,7 +1229,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 2; mask 0x0004; underlined (redundant in BIFF5-BIFF8) // bit: 3; mask 0x0008; strike $isStrike = (0x0008 & $this->_GetInt2d($recordData, 2)) >> 3; - if ($isStrike) $objFont->setStriketrough(true); + if ($isStrike) $objFont->setStrikethrough(true); // offset: 4; size: 2; colour index $colorIndex = $this->_GetInt2d($recordData, 4); @@ -1450,6 +1494,24 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 29-23; mask: 0x3F800000; right color $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $this->_GetInt4d($recordData, 10)) >> 23; + // bit: 30; mask: 0x40000000; 1 = diagonal line from top left to right bottom + $diagonalDown = (0x40000000 & $this->_GetInt4d($recordData, 10)) >> 30 ? + true : false; + + // bit: 31; mask: 0x80000000; 1 = diagonal line from bottom left to top right + $diagonalUp = (0x80000000 & $this->_GetInt4d($recordData, 10)) >> 31 ? + true : false; + + if ($diagonalUp == false && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp == true && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); + } elseif ($diagonalUp == false && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } elseif ($diagonalUp == true && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); + } + // offset: 14; size: 4; // bit: 6-0; mask: 0x0000007F; top color $objStyle->getBorders()->getTop()->colorIndex = (0x0000007F & $this->_GetInt4d($recordData, 14)) >> 0; @@ -1457,6 +1519,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 13-7; mask: 0x00003F80; bottom color $objStyle->getBorders()->getBottom()->colorIndex = (0x00003F80 & $this->_GetInt4d($recordData, 14)) >> 7; + // bit: 20-14; mask: 0x001FC000; diagonal color + $objStyle->getBorders()->getDiagonal()->colorIndex = (0x001FC000 & $this->_GetInt4d($recordData, 14)) >> 14; + + // bit: 24-21; mask: 0x01E00000; diagonal style + if ($bordersDiagonalStyle = $this->_mapBorderStyle((0x01E00000 & $this->_GetInt4d($recordData, 14)) >> 21)) { + $objStyle->getBorders()->getDiagonal()->setBorderStyle($bordersDiagonalStyle); + } + // bit: 31-26; mask: 0xFC000000 fill pattern if ($fillType = $this->_mapFillPattern((0xFC000000 & $this->_GetInt4d($recordData, 14)) >> 26)) { $objStyle->getFill()->setFillType($fillType); @@ -1548,6 +1618,182 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * + */ + private function _readXfExt() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0x087D = repeated header + + // offset: 2; size: 2 + + // offset: 4; size: 8; not used + + // offset: 12; size: 2; record version + + // offset: 14; size: 2; index to XF record which this record modifies + $ixfe = $this->_GetInt2d($recordData, 14); + + // offset: 16; size: 2; not used + + // offset: 18; size: 2; number of extension properties that follow + $cexts = $this->_GetInt2d($recordData, 18); + + // start reading the actual extension data + $offset = 20; + while ($offset < $length) { + // extension type + $extType = $this->_GetInt2d($recordData, $offset); + + // extension length + $cb = $this->_GetInt2d($recordData, $offset + 2); + + // extension data + $extData = substr($recordData, $offset + 4, $cb); + + switch ($extType) { + case 4: // fill start color + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getStartColor()->setRGB($rgb); + unset($fill->startcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 5: // fill end color + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getEndColor()->setRGB($rgb); + unset($fill->endcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 7: // border color top + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $top = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getTop(); + $top->getColor()->setRGB($rgb); + unset($top->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 8: // border color bottom + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $bottom = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getBottom(); + $bottom->getColor()->setRGB($rgb); + unset($bottom->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 9: // border color left + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $left = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getLeft(); + $left->getColor()->setRGB($rgb); + unset($left->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 10: // border color right + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $right = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getRight(); + $right->getColor()->setRGB($rgb); + unset($right->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 11: // border color diagonal + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $diagonal = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getDiagonal(); + $diagonal->getColor()->setRGB($rgb); + unset($diagonal->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 13: // font color + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $font = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFont(); + $font->getColor()->setRGB($rgb); + unset($font->colorIndex); // normal color index does not apply, discard + } + } + break; + } + + $offset += $cb; + } + } + + } + /** * Read STYLE record */ @@ -1636,6 +1882,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 4; size: 1; sheet state $rec_typeFlag = ord($recordData{4}); + switch (ord($recordData{4})) { + case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + case 0x01: $sheetState = PHPExcel_Worksheet::SHEETSTATE_HIDDEN; break; + case 0x02: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN; break; + default: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + } // offset: 5; size: 1; sheet type $rec_visibilityFlag = ord($recordData{5}); @@ -1650,7 +1902,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } $this->_sheets[] = array( 'name' => $rec_name, - 'offset' => $rec_offset + 'offset' => $rec_offset, + 'sheetState' => $sheetState, ); } @@ -1779,6 +2032,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $nlen = ord($recordData{3}); // offset: 4; size: 2; size of the formula data (it can happen that this is zero) + // note: there can also be additional data, this is not included in $flen $flen = $this->_GetInt2d($recordData, 4); // offset: 14; size: var; Name (Unicode string without length field) @@ -1786,7 +2040,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: var; size: $flen; formula data $offset = 14 + $string['size']; - $formulaStructure = pack('v', $flen) . substr($recordData, $offset, $flen); + $formulaStructure = pack('v', $flen) . substr($recordData, $offset); try { $formula = $this->_getFormulaFromStructure($formulaStructure); @@ -1882,7 +2136,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // look up limit position foreach ($spliceOffsets as $spliceOffset) { - if ($pos < $spliceOffset) { + // it can happen that the string is empty, therefore we need + // <= and not just < + if ($pos <= $spliceOffset) { $limitpos = $spliceOffset; break; } @@ -2320,12 +2576,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 1: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT); break; } - if (!$this->_isFitToPages) { - $this->_phpSheet->getPageSetup()->setScale($scale); - } else { - $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth); - $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight); - } + $this->_phpSheet->getPageSetup()->setScale($scale, false); + $this->_phpSheet->getPageSetup()->setFitToPage((bool) $this->_isFitToPages); + $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth, false); + $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight, false); } // offset: 16; size: 8; header margin (IEEE 754 floating-point value) @@ -2350,16 +2604,61 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // move stream pointer to next record $this->_pos += 4 + $length; - if (!$this->_readDataOnly) { - // offset: 0; size: 2; - - // bit 0, mask 0x01; sheet protection - $isSheetProtected = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; - switch ($isSheetProtected) { - case 0: break; - case 1: $this->_phpSheet->getProtection()->setSheet(true); break; - } + if ($this->_readDataOnly) { + return; } + + // offset: 0; size: 2; + + // bit 0, mask 0x01; 1 = sheet is protected + $bool = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; + $this->_phpSheet->getProtection()->setSheet((bool)$bool); + } + + /** + * SCENPROTECT + */ + private function _readScenProtect() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit: 0, mask 0x01; 1 = scenarios are protected + $bool = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setScenarios((bool)$bool); + } + + /** + * OBJECTPROTECT + */ + private function _readObjectProtect() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit: 0, mask 0x01; 1 = objects are protected + $bool = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setObjects((bool)$bool); } /** @@ -2444,6 +2743,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $this->_phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden); $this->_phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level); $this->_phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed); + $this->_phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -2476,8 +2776,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 6; size: 2; - // bit: 14-0; mask: 0x7FF; height of the row, in twips = 1/20 of a point - $height = (0x7FF & $this->_GetInt2d($recordData, 6)) >> 0; + // bit: 14-0; mask: 0x7FFF; height of the row, in twips = 1/20 of a point + $height = (0x7FFF & $this->_GetInt2d($recordData, 6)) >> 0; // bit: 15: mask: 0x8000; 0 = row has custom height; 1= row has default height $useDefaultHeight = (0x8000 & $this->_GetInt2d($recordData, 6)) >> 15; @@ -2504,11 +2804,15 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $isHidden = (0x00000020 & $this->_GetInt4d($recordData, 12)) >> 5; $this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden); - // bit: 7; mask: 0x00000080; 1 = row has explicit default format - $hasDefaultFormat = (0x00000080 & $this->_GetInt4d($recordData, 12)) >> 7; + // bit: 7; mask: 0x00000080; 1 = row has explicit format + $hasExplicitFormat = (0x00000080 & $this->_GetInt4d($recordData, 12)) >> 7; - // bit: 27-16; mask: 0x0FFF0000; only applies when hasDefaultFormat = 1; index to XF record + // bit: 27-16; mask: 0x0FFF0000; only applies when hasExplicitFormat = 1; index to XF record $xfIndex = (0x0FFF0000 & $this->_GetInt4d($recordData, 12)) >> 16; + + if ($hasExplicitFormat) { + $this->_phpSheet->getRowDimension($r + 1)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } } } @@ -2541,7 +2845,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 4; RK value $rknum = $this->_GetInt4d($recordData, 6); @@ -2549,7 +2853,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell @@ -2584,7 +2888,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 4; index to SST record $index = $this->_GetInt4d($recordData, 6); @@ -2626,7 +2930,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -2667,13 +2971,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: var; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, $offset); + $xfIndex = $this->_GetInt2d($recordData, $offset); // offset: var; size: 4; RK value $numValue = $this->_GetIEEE754($this->_GetInt4d($recordData, $offset + 2)); if (!$this->_readDataOnly) { // add style - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell value @@ -2710,13 +3014,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); $numValue = $this->_extractNumber(substr($recordData, 6, 8)); // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell value @@ -2760,6 +3064,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 1; mask: 0x0002; 1 = calculate on open // bit: 2; mask: 0x0008; 1 = part of a shared formula $isPartOfSharedFormula = (bool) (0x0008 & $options); + + // WARNING: + // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true + // the formula data may be ordinary formula data, therefore we need to check + // explicitly for the tExp token (0x01) + $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; + if ($isPartOfSharedFormula) { // part of shared formula which means there will be a formula with a tExp token and nothing else // get the base cell, grab tExp token @@ -2774,7 +3085,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 16: size: 4; not used // offset: 4; size: 2; XF index - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 8; result of the formula if ( (ord($recordData{6}) == 0) @@ -2827,7 +3138,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // store the formula @@ -2939,7 +3250,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 1; the boolean value or error value $boolErr = ord($recordData{6}); @@ -2965,7 +3276,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3000,8 +3311,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - $xfindex = $this->_GetInt2d($recordData, 4 + 2 * $i); - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $xfIndex = $this->_GetInt2d($recordData, 4 + 2 * $i); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3037,7 +3348,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; XF index - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // add cell value // todo: what if string is very long? continue record @@ -3052,7 +3363,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3078,11 +3389,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; XF index - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } @@ -3209,6 +3520,56 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * Read SELECTION record. There is one such record for each pane in the sheet. + */ + private function _readSelection() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 1; pane identifier + $paneId = ord($recordData{0}); + + // offset: 1; size: 2; index to row of the active cell + $r = $this->_GetInt2d($recordData, 1); + + // offset: 3; size: 2; index to column of the active cell + $c = $this->_GetInt2d($recordData, 3); + + // offset: 5; size: 2; index into the following cell range list to the + // entry that contains the active cell + $index = $this->_GetInt2d($recordData, 5); + + // offset: 7; size: var; cell range address list containing all selected cell ranges + $data = substr($recordData, 7); + $cellRangeAddressList = $this->_readBIFF5CellRangeAddressList($data); // note: also BIFF8 uses BIFF5 syntax + + $selectedCells = $cellRangeAddressList['cellRangeAddresses'][0]; + + // first row '1' + last row '16384' indicates that full column is selected (apparently also in BIFF8!) + if (preg_match('/^([A-Z]+1\:[A-Z]+)16384$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)16384$/', '${1}1048576', $selectedCells); + } + + // first row '1' + last row '65536' indicates that full column is selected + if (preg_match('/^([A-Z]+1\:[A-Z]+)65536$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)65536$/', '${1}1048576', $selectedCells); + } + + // first column 'A' + last column 'IV' indicates that full row is selected + if (preg_match('/^(A[0-9]+\:)IV([0-9]+)$/', $selectedCells)) { + $selectedCells = preg_replace('/^(A[0-9]+\:)IV([0-9]+)$/', '${1}XFD${2}', $selectedCells); + } + + $this->_phpSheet->setSelectedCells($selectedCells); + } + } + /** * MERGEDCELLS * @@ -3307,6 +3668,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader switch ($hyperlinkType) { case 'URL': + // section 5.58.2: Hyperlink containing a URL + // e.g. http://example.org/index.php + // offset: var; size: 16; GUID of URL Moniker $offset += 16; // offset: var; size: 4; size (in bytes) of character array of the URL including trailing zero word @@ -3318,21 +3682,73 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $offset += $us; break; + case 'local': + // section 5.58.3: Hyperlink to local file + // examples: + // mydoc.txt + // ../../somedoc.xls#Sheet!A1 + + // offset: var; size: 16; GUI of File Moniker + $offset += 16; + + // offset: var; size: 2; directory up-level count. + $upLevelCount = $this->_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 4; character count of the shortened file path and name, including trailing zero word + $sl = $this->_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size: sl; character array of the shortened file path and name in 8.3-DOS-format (compressed Unicode string) + $shortenedFilePath = substr($recordData, $offset, $sl); + $shortenedFilePath = $this->_encodeUTF16($shortenedFilePath, true); + $shortenedFilePath = substr($shortenedFilePath, 0, -1); // remove trailing zero + + $offset += $sl; + + // offset: var; size: 24; unknown sequence + $offset += 24; + + // extended file path + // offset: var; size: 4; size of the following file link field including string lenth mark + $sz = $this->_GetInt4d($recordData, $offset); + $offset += 4; + + // only present if $sz > 0 + if ($sz > 0) { + // offset: var; size: 4; size of the character array of the extended file path and name + $xl = $this->_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size 2; unknown + $offset += 2; + + // offset: var; size $xl; character array of the extended file path and name. + $extendedFilePath = substr($recordData, $offset, $xl); + $extendedFilePath = $this->_encodeUTF16($extendedFilePath, false); + $offset += $xl; + } + + // construct the path + $url = str_repeat('..\\', $upLevelCount); + $url .= ($sz > 0) ? + $extendedFilePath : $shortenedFilePath; // use extended path if available + $url .= $hasText ? '#' : ''; + + break; + + + case 'UNC': + // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path + // todo: implement + return; + case 'workbook': // section 5.58.5: Hyperlink to the Current Workbook // e.g. Sheet2!B1:C2, stored in text mark field $url = 'sheet://'; break; - case 'local': - // section 5.58.2: Hyperlink containing a URL - // e.g. http://example.org/index.php - // todo: implement - - case 'UNC': - // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path - // todo: implement - default: return; @@ -3354,6 +3770,132 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * Read SHEETLAYOUT record. Stores sheet tab color information. + */ + private function _readSheetLayout() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // local pointer in record data + $offset = 0; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; repeated record identifier 0x0862 + + // offset: 2; size: 10; not used + + // offset: 12; size: 4; size of record data + // Excel 2003 uses size of 0x14 (documented), Excel 2007 uses size of 0x28 (not documented?) + $sz = $this->_GetInt4d($recordData, 12); + + switch ($sz) { + case 0x14: + // offset: 16; size: 2; color index for sheet tab + $colorIndex = $this->_GetInt2d($recordData, 16); + $color = $this->_readColor($colorIndex); + $this->_phpSheet->getTabColor()->setRGB($color['rgb']); + break; + + case 0x28: + // TODO: Investigate structure for .xls SHEETLAYOUT record as saved by MS Office Excel 2007 + return; + break; + } + } + } + + /** + * Read SHEETPROTECTION record + */ + private function _readSheetProtection() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; repeated record header + + // offset: 2; size: 9; not used + + // offset: 11; size: 8; unknown data + + // offset: 19; size: 2; option flags + $options = $this->_GetInt2d($recordData, 19); + + // bit: 0; mask 0x0001; 1 = user may edit objects, 0 = users must not edit objects + $bool = (0x0001 & $options) >> 0; + $this->_phpSheet->getProtection()->setObjects(!$bool); + + // bit: 1; mask 0x0002; edit scenarios + $bool = (0x0002 & $options) >> 1; + $this->_phpSheet->getProtection()->setScenarios(!$bool); + + // bit: 2; mask 0x0004; format cells + $bool = (0x0004 & $options) >> 2; + $this->_phpSheet->getProtection()->setFormatCells(!$bool); + + // bit: 3; mask 0x0008; format columns + $bool = (0x0008 & $options) >> 3; + $this->_phpSheet->getProtection()->setFormatColumns(!$bool); + + // bit: 4; mask 0x0010; format rows + $bool = (0x0010 & $options) >> 4; + $this->_phpSheet->getProtection()->setFormatRows(!$bool); + + // bit: 5; mask 0x0020; insert columns + $bool = (0x0020 & $options) >> 5; + $this->_phpSheet->getProtection()->setInsertColumns(!$bool); + + // bit: 6; mask 0x0040; insert rows + $bool = (0x0040 & $options) >> 6; + $this->_phpSheet->getProtection()->setInsertRows(!$bool); + + // bit: 7; mask 0x0080; insert hyperlinks + $bool = (0x0080 & $options) >> 7; + $this->_phpSheet->getProtection()->setInsertHyperlinks(!$bool); + + // bit: 8; mask 0x0100; delete columns + $bool = (0x0100 & $options) >> 8; + $this->_phpSheet->getProtection()->setDeleteColumns(!$bool); + + // bit: 9; mask 0x0200; delete rows + $bool = (0x0200 & $options) >> 9; + $this->_phpSheet->getProtection()->setDeleteRows(!$bool); + + // bit: 10; mask 0x0400; select locked cells + $bool = (0x0400 & $options) >> 10; + $this->_phpSheet->getProtection()->setSelectLockedCells(!$bool); + + // bit: 11; mask 0x0800; sort cell range + $bool = (0x0800 & $options) >> 11; + $this->_phpSheet->getProtection()->setSort(!$bool); + + // bit: 12; mask 0x1000; auto filter + $bool = (0x1000 & $options) >> 12; + $this->_phpSheet->getProtection()->setAutoFilter(!$bool); + + // bit: 13; mask 0x2000; pivot tables + $bool = (0x2000 & $options) >> 13; + $this->_phpSheet->getProtection()->setPivotTables(!$bool); + + // bit: 14; mask 0x4000; select unlocked cells + $bool = (0x4000 & $options) >> 14; + $this->_phpSheet->getProtection()->setSelectUnlockedCells(!$bool); + + // offset: 21; size: 2; not used + } + /** * Read RANGEPROTECTION record * Reading of this record is based on Microsoft Office Excel 97-2000 Binary File Format Specification, @@ -3523,9 +4065,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // dirty check to see if CONTINUE record could be a camouflaged MSODRAWING record // look inside CONTINUE record to see if it looks like a part of an Escher stream // we know that Escher stream may be split at least at + // 0xF003 MsofbtSpgrContainer // 0xF004 MsofbtSpContainer // 0xF00D MsofbtClientTextbox - $validSplitPoints = array(0xF004, 0xF00D); // add identifiers if we find more + $validSplitPoints = array(0xF003, 0xF004, 0xF00D); // add identifiers if we find more $splitPoint = $this->_GetInt2d($recordData, 2); if (in_array($splitPoint, $validSplitPoints)) { @@ -3772,6 +4315,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 'tRef3d': // 3d cell reference case 'tArea3d': // 3d cell range reference case 'tRefN': + case 'tAreaN': case 'tStr': // string $formulaStrings[] = "$space1$space0{$token['data']}"; unset($space0, $space1); @@ -4260,11 +4804,21 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $data = $this->_getFormulaFromData(substr($formulaData, 3, $subSize)); break; - case 0x4C: // Relative reference, used in shared formulas and some other places + case 0x2C: // Relative reference, used in shared formulas and some other places + case 0x4C: + case 0x6C: $name = 'tRefN'; $size = 5; $data = $this->_readBIFF8CellAddressB(substr($formulaData, 1, 4), $baseCell); break; + + case 0x2D: + case 0x4D: + case 0x6D: + $name = 'tAreaN'; + $size = 9; + $data = $this->_readBIFF8CellRangeAddressB(substr($formulaData, 1, 8), $baseCell); + break; case 0x3A: // 3d reference to cell case 0x5A: @@ -4504,6 +5058,88 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader return "$fc$fr:$lc$lr"; } + /** + * Reads a cell range address in BIFF8 for shared formulas. Uses positive and negative values for row and column + * to indicate offsets from a base cell + * section 3.3.4 + * + * @param string $subData + * @param string $baseCell Base cell + * @return string Cell range address + */ + private function _readBIFF8CellRangeAddressB($subData, $baseCell = 'A1') + { + list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); + $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; + + // TODO: if cell range is just a single cell, should this funciton + // not just return e.g. 'A1' and not 'A1:A1' ? + + // offset: 0; size: 2; first row + $frIndex = $this->_GetInt2d($subData, 0); // adjust below + + // offset: 2; size: 2; relative index to first row (0... 65535) should be treated as offset (-32768... 32767) + $lrIndex = $this->_GetInt2d($subData, 2); // adjust below + + // offset: 4; size: 2; first column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $fcIndex = 0x00FF & $this->_GetInt2d($subData, 4); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & $this->_GetInt2d($subData, 4))) { + // absolute column index + $fc = PHPExcel_Cell::stringFromColumnIndex($fcIndex); + $fc = '$' . $fc; + } else { + // column offset + $fcIndex = ($fcIndex <= 127) ? $fcIndex : $fcIndex - 256; + $fc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $fcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & $this->_GetInt2d($subData, 4))) { + // absolute row index + $fr = $frIndex + 1; + $fr = '$' . $fr; + } else { + // row offset + $frIndex = ($frIndex <= 32767) ? $frIndex : $frIndex - 65536; + $fr = $baseRow + $frIndex; + } + + // offset: 6; size: 2; last column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $lcIndex = 0x00FF & $this->_GetInt2d($subData, 6); + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & $this->_GetInt2d($subData, 6))) { + // absolute column index + $lc = PHPExcel_Cell::stringFromColumnIndex($lcIndex); + $lc = '$' . $lc; + } else { + // column offset + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & $this->_GetInt2d($subData, 6))) { + // absolute row index + $lr = $lrIndex + 1; + $lr = '$' . $lr; + } else { + // row offset + $lrIndex = ($lrIndex <= 32767) ? $lrIndex : $lrIndex - 65536; + $lr = $baseRow + $lrIndex; + } + + return "$fc$fr:$lc$lr"; + } + /** * Read BIFF8 cell range address list * section 2.5.15 @@ -4531,6 +5167,33 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader ); } + /** + * Read BIFF5 cell range address list + * section 2.5.15 + * + * @param string $subData + * @return array + */ + private function _readBIFF5CellRangeAddressList($subData) + { + $cellRangeAddresses = array(); + + // offset: 0; size: 2; number of the following cell range addresses + $nm = $this->_GetInt2d($subData, 0); + + $offset = 2; + // offset: 2; size: 6 * $nm; list of $nm (fixed) cell range addresses + for ($i = 0; $i < $nm; ++$i) { + $cellRangeAddresses[] = $this->_readBIFF5CellRangeAddressFixed(substr($subData, $offset, 6)); + $offset += 6; + } + + return array( + 'size' => 2 + 6 * $nm, + 'cellRangeAddresses' => $cellRangeAddresses, + ); + } + /** * Get a sheet range like Sheet1:Sheet3 from REF index * Note: If there is only one sheet in the range, one gets e.g Sheet1 diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php b/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php index 3cdc38449..fd9f138ed 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ @@ -62,7 +62,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/S * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel5_Escher { diff --git a/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php b/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php index a173b3f0f..c81297176 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php +++ b/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Reader_IReadFilter { diff --git a/libraries/PHPExcel/PHPExcel/Reader/IReader.php b/libraries/PHPExcel/PHPExcel/Reader/IReader.php index df758e0d1..52e0c2e89 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/IReader.php +++ b/libraries/PHPExcel/PHPExcel/Reader/IReader.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Reader_IReader { diff --git a/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php b/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php new file mode 100644 index 000000000..618a1f2d4 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php @@ -0,0 +1,500 @@ +_readDataOnly; + } + + /** + * Set read data only + * + * @param boolean $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadDataOnly($pValue = false) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Get which sheets to load + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadSheetsOnly($value = null) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = null; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Create a new PHPExcel_Reader_OOCalc + */ + public function __construct() { + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Load file + $zip = new ZipArchive; + if ($zip->open($pFilename) === true) { + // check if it is an OOXML archive + $mimeType = $zip->getFromName("mimetype"); + + $zip->close(); + + return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet'); + } + + return false; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $zip = new ZipArchive; + if ($zip->open($pFilename) === true) { +// echo '

Meta Information

'; + $xml = simplexml_load_string($zip->getFromName("meta.xml")); + $namespacesMeta = $xml->getNamespaces(true); +// echo '
';
+//			print_r($namespacesMeta);
+//			echo '

'; + + $docProps = $objPHPExcel->getProperties(); + $officeProperty = $xml->children($namespacesMeta['office']); + foreach($officeProperty as $officePropertyData) { + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { +// echo $propertyName.' = '.$propertyValue.'
'; + + switch ($propertyName) { + case 'title' : + $docProps->setTitle($propertyValue); + break; + case 'subject' : + $docProps->setSubject($propertyValue); + break; + case 'creator' : + $docProps->setCreator($propertyValue); + break; + case 'date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'description' : + $docProps->setDescription($propertyValue); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); + +// echo $propertyName.' = '.$propertyValue.'
'; +// foreach ($propertyValueAttributes as $key => $value) { +// echo $key.' = '.$value.'
'; +// } +// echo '
'; +// + switch ($propertyName) { + case 'keyword' : + $docProps->setKeywords($propertyValue); + break; + } + } + } + + +// echo '

Workbook Content

'; + $xml = simplexml_load_string($zip->getFromName("content.xml")); + $namespacesContent = $xml->getNamespaces(true); +// echo '
';
+//			print_r($namespacesContent);
+//			echo '

'; + + $workbook = $xml->children($namespacesContent['office']); + foreach($workbook->body->spreadsheet as $workbookData) { + $workbookData = $workbookData->children($namespacesContent['table']); + $worksheetID = 0; + foreach($workbookData->table as $worksheetDataSet) { + $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// print_r($worksheetData); +// echo '
'; + $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// print_r($worksheetDataAttributes); +// echo '
'; + if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && + (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { + continue; + } + +// echo '

Worksheet '.$worksheetDataAttributes['name'].'

'; + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheetDataAttributes['name'])) { + $worksheetName = $worksheetDataAttributes['name']; + $objPHPExcel->getActiveSheet()->setTitle($worksheetName); + } + + $rowID = 1; + foreach($worksheetData as $key => $rowData) { +// echo ''.$key.'
'; + switch ($key) { + case 'table-row' : + $columnID = 'A'; + foreach($rowData as $key => $cellData) { +// echo ''.$columnID.$rowID.'
'; + $cellDataText = $cellData->children($namespacesContent['text']); + $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); + $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); + +// echo 'Office Attributes: '; +// print_r($cellDataOfficeAttributes); +// echo '
Table Attributes: '; +// print_r($cellDataTableAttributes); +// echo '
Cell Data Text'; +// print_r($cellDataText); +// echo '
'; +// + $type = $formatting = $hyperlink = null; + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cellDataTableAttributes['formula'])) { + $cellDataFormula = $cellDataTableAttributes['formula']; + $hasCalculatedValue = true; + } + + if (isset($cellDataText->p)) { +// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'
'; + switch ($cellDataOfficeAttributes['value-type']) { + case 'string' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + $dataValue = $cellDataText->p; + if (isset($dataValue->a)) { + $dataValue = $dataValue->a; + $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); + $hyperlink = $cellXLinkAttributes['href']; + } + break; + case 'boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $dataValue = ($cellDataText->p == 'TRUE') ? True : False; + break; + case 'float' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + break; + case 'date' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellDataOfficeAttributes['date-value'])); + if ($dataValue != floor($dataValue)) { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + } else { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; + } + break; + case 'time' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + break; + } +// echo 'Data value is '.$dataValue.'
'; +// if (!is_null($hyperlink)) { +// echo 'Hyperlink is '.$hyperlink.'
'; +// } + } + + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; +// echo 'Formula: '.$cellDataFormula.'
'; + $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); + $temp = explode('"',$cellDataFormula); + foreach($temp as $key => &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if (($key % 2) == 0) { + $value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value); + $value = preg_replace('/\[\.(.*)\]/Ui','$1',$value); + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'Adjusted Formula: '.$cellDataFormula.'
'; + } + + if (!is_null($type)) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$dataValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($dataValue); + } + if (($cellDataOfficeAttributes['value-type'] == 'date') || + ($cellDataOfficeAttributes['value-type'] == 'time')) { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rowID)->getNumberFormat()->setFormatCode($formatting); + } + if (!is_null($hyperlink)) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->getHyperlink()->setUrl($hyperlink); + } + } + + // Merged cells + if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { + $columnTo = $columnID; + if (isset($cellDataTableAttributes['number-columns-spanned'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + } + $rowTo = $rowID; + if (isset($cellDataTableAttributes['number-rows-spanned'])) { + $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; + } + $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + + if (isset($cellDataTableAttributes['number-columns-repeated'])) { +// echo 'Repeated '.$cellDataTableAttributes['number-columns-repeated'].' times
'; + $columnID = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-repeated'] - 2); + } + ++$columnID; + } + ++$rowID; + break; + } + } + ++$worksheetID; + } + } + + } + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_OOCalc + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Reader/SYLK.php b/libraries/PHPExcel/PHPExcel/Reader/SYLK.php new file mode 100644 index 000000000..a9bd64717 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Reader/SYLK.php @@ -0,0 +1,506 @@ +_inputEncoding = 'ANSI'; + $this->_delimiter = ';'; + $this->_enclosure = '"'; + $this->_lineEnding = PHP_EOL; + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Read sample data (first 2 KB will do) + $fh = fopen($pFilename, 'r'); + $data = fread($fh, 2048); + fclose($fh); + + // Count delimiters in file + $delimiterCount = substr_count($data, ';'); + if ($delimiterCount < 1) { + return false; + } + + // Analyze first line looking for ID; signature + $lines = explode("\n", $data); + if (substr($lines[0],0,4) != 'ID;P') { + return false; + } + + return true; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + } + + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'ANSI') + { + $this->_inputEncoding = $pValue; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Create new PHPExcel + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); + + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); + + // Open file + $fileHandle = fopen($pFilename, 'r'); + if ($fileHandle === false) { + throw new Exception("Could not open file $pFilename for reading."); + } + + // Loop through file + $rowData = array(); + $column = $row = ''; + while (($rowData = fgets($fileHandle)) !== FALSE) { + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + $dataType = array_shift($rowData); + // Read shared styles + if ($dataType == 'P') { + $formatArray = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'P' : $formatArray['numberformat']['code'] = str_replace($fromFormats,$toFormats,substr($rowDatum,1)); + break; + case 'E' : + case 'F' : $formatArray['font']['name'] = substr($rowDatum,1); + break; + case 'L' : $formatArray['font']['size'] = substr($rowDatum,1); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i_formats['P'.$this->_format++] = $formatArray; + // Read cell value data + } elseif ($dataType == 'C') { + $hasCalculatedValue = false; + $cellData = $cellDataFormula = ''; + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'K' : $cellData = substr($rowDatum,1); + break; + case 'E' : $cellDataFormula = '='.substr($rowDatum,1); + // Convert R1C1 style references to A1 style references (but only when not quoted) + $temp = explode('"',$cellDataFormula); + foreach($temp as $key => &$value) { + // Only count/replace in alternate array entries + if (($key % 2) == 0) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $row; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $column; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); + $hasCalculatedValue = true; + break; + } + } + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + // Set cell value + $objPHPExcel->getActiveSheet()->setCellValue($columnLetter.$row, (($hasCalculatedValue) ? $cellDataFormula : $cellData)); + if ($hasCalculatedValue) { + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData); + } + // Read cell formatting + } elseif ($dataType == 'F') { + $formatStyle = $columnWidth = $styleSettings = ''; + $styleData = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'P' : $formatStyle = $rowDatum; + break; + case 'W' : list($startCol,$endCol,$columnWidth) = explode(' ',substr($rowDatum,1)); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i '') && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); + } + if ((count($styleData) > 0) && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData); + } + if ($columnWidth > '') { + if ($startCol == $endCol) { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + } else { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + do { + $objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth); + } while ($startCol != $endCol); + } + } + } else { + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + } + } + } + } + + // Close file + fclose($fileHandle); + + // Return + return $objPHPExcel; + } + + /** + * Get delimiter + * + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } + + /** + * Set delimiter + * + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Reader_SYLK + */ + public function setDelimiter($pValue = ',') { + $this->_delimiter = $pValue; + return $this; + } + + /** + * Get enclosure + * + * @return string + */ + public function getEnclosure() { + return $this->_enclosure; + } + + /** + * Set enclosure + * + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Reader_SYLK + */ + public function setEnclosure($pValue = '"') { + if ($pValue == '') { + $pValue = '"'; + } + $this->_enclosure = $pValue; + return $this; + } + + /** + * Get line ending + * + * @return string + */ + public function getLineEnding() { + return $this->_lineEnding; + } + + /** + * Set line ending + * + * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) + * @return PHPExcel_Reader_SYLK + */ + public function setLineEnding($pValue = PHP_EOL) { + $this->_lineEnding = $pValue; + return $this; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_SYLK + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Reader/Serialized.php b/libraries/PHPExcel/PHPExcel/Reader/Serialized.php index b95204ce8..120a6781c 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Serialized.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Serialized.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Serialized implements PHPExcel_Reader_IReader { diff --git a/libraries/PHPExcel/PHPExcel/ReferenceHelper.php b/libraries/PHPExcel/PHPExcel/ReferenceHelper.php index 886ce286c..175bba122 100644 --- a/libraries/PHPExcel/PHPExcel/ReferenceHelper.php +++ b/libraries/PHPExcel/PHPExcel/ReferenceHelper.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.2, 2010-01-11 */ @@ -60,8 +60,8 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaToken.php'; * PHPExcel_ReferenceHelper (Singleton) * * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_ReferenceHelper { @@ -86,20 +86,20 @@ class PHPExcel_ReferenceHelper } /** - * Create a new PHPExcel_Calculation + * Create a new PHPExcel_ReferenceHelper */ protected function __construct() { } - /** - * Insert a new column, updating all possible related data - * - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @throws Exception - */ - public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @throws Exception + */ + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { // Get a copy of the cell collection /*$aTemp = $pSheet->getCellCollection(); $aCellCollection = array(); @@ -108,15 +108,15 @@ class PHPExcel_ReferenceHelper }*/ $aCellCollection = $pSheet->getCellCollection(); - // Get coordinates of $pBefore - $beforeColumn = 'A'; - $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); // Clear cells if we are removing columns or rows - $highestColumn = $pSheet->getHighestColumn(); - $highestRow = $pSheet->getHighestRow(); + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); // 1. Clear column strips if we are removing columns if ($pNumCols < 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols > 0) { @@ -155,7 +155,7 @@ class PHPExcel_ReferenceHelper // Should the cell be updated? Move value and cellXf index from one cell to another. if ( (PHPExcel_Cell::columnIndexFromString( $cell->getColumn() ) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)) && - ($cell->getRow() >= $beforeRow) + ($cell->getRow() >= $beforeRow) ) { // Update cell styles @@ -181,8 +181,8 @@ class PHPExcel_ReferenceHelper // Duplicate styles for the newly inserted cells - $highestColumn = $pSheet->getHighestColumn(); - $highestRow = $pSheet->getHighestRow(); + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); if ($pNumCols > 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 > 0) { for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { @@ -303,14 +303,13 @@ class PHPExcel_ReferenceHelper // Update worksheet: merge cells - $aMergeCells = array_reverse($pSheet->getMergeCells(), true); - foreach ($aMergeCells as $key => $value) { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->mergeCells( $newReference ); - $pSheet->unmergeCells( $key ); - } + $aNewMergeCells[$newReference] = $newReference; } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array // Update worksheet: protected cells @@ -365,57 +364,74 @@ class PHPExcel_ReferenceHelper // Garbage collect $pSheet->garbageCollect(); - } - - /** - * Update references within formulas - * - * @param string $pFormula Formula to update - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @return string Updated formula - * @throws Exception - */ - public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - // Formula stack - $executableFormulaArray = array(); + } + /** + * Update references within formulas + * + * @param string $pFormula Formula to update + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @return string Updated formula + * @throws Exception + */ + public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { // Parse formula into a tree of tokens $tokenisedFormula = PHPExcel_Calculation::getInstance()->parseFormula($pFormula); + $newCellTokens = $cellTokens = array(); + $adjustCount = 0; // Build the translation table of cell tokens foreach($tokenisedFormula as $token) { + $token = $token['value']; if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) { - $newCellTokens[] = $this->updateCellReference($token, $pBefore, $pNumCols, $pNumRows); - $cellTokens[] = '/'.$token.'/'; + list($column,$row) = PHPExcel_Cell::coordinateFromString($token); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString($column) + 100000; + $row += 10000000; + $cellIndex = $column.$row; + if (!isset($cellTokens[$cellIndex])) { + $newReference = $this->updateCellReference($token, $pBefore, $pNumCols, $pNumRows); + if ($newReference !== $token) { + $newCellTokens[$cellIndex] = preg_quote($newReference); + $cellTokens[$cellIndex] = '/(? $formulaBlock) { + foreach($formulaBlocks as $i => &$formulaBlock) { // Only count/replace in alternate array entries - if (($i++ % 2) == 0) { - $formulaBlocks[$formulaBlockKey] = preg_replace($cellTokens,$newCellTokens,$formulaBlock); + if (($i % 2) == 0) { + $formulaBlock = preg_replace($cellTokens,$newCellTokens,$formulaBlock); } } + unset($formulaBlock); + // Then rebuild the formula string return implode('"',$formulaBlocks); - } + } - /** - * Update cell reference - * - * @param string $pCellRange Cell range - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell range - * @throws Exception - */ - public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + /** + * Update cell reference + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws Exception + */ + public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { // Is it in another worksheet? Will not have to update anything. if (strpos($pCellRange, "!") !== false) { return $pCellRange; @@ -423,24 +439,28 @@ class PHPExcel_ReferenceHelper } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) { // Single cell return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows); - } else if (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { + } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { // Range return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows); } else { // Return original return $pCellRange; } - } + } - /** - * Update named formulas (i.e. containing worksheet references / named ranges) - * - * @param PHPExcel $pPhpExcel Object to update - * @param string $oldName Old name (name to replace) - * @param string $newName New name - */ - public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { - foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { + /** + * Update named formulas (i.e. containing worksheet references / named ranges) + * + * @param PHPExcel $pPhpExcel Object to update + * @param string $oldName Old name (name to replace) + * @param string $newName New name + */ + public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { + if ($oldName == '') { + return; + } + + foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { foreach ($sheet->getCellCollection(false) as $cell) { if (!is_null($cell) && $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { $formula = $cell->getValue(); @@ -451,56 +471,56 @@ class PHPExcel_ReferenceHelper } } } - } - } + } + } - /** - * Update cell range - * - * @param string $pCellRange Cell range - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell range - * @throws Exception - */ - private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { + /** + * Update cell range + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws Exception + */ + private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { // Update range $range = PHPExcel_Cell::splitRange($pCellRange); - for ($i = 0; $i < count($range); $i++) { - for ($j = 0; $j < count($range[$i]); $j++) { + for ($i = 0; $i < count($range); ++$i) { + for ($j = 0; $j < count($range[$i]); ++$j) { $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows); } } // Recreate range string return PHPExcel_Cell::buildRange($range); - } else { - throw new Exception("Only cell ranges may be passed to this method."); - } - } + } else { + throw new Exception("Only cell ranges may be passed to this method."); + } + } - /** - * Update single cell reference - * - * @param string $pCellReference Single cell reference - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell reference - * @throws Exception - */ - private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { - // Get coordinates of $pBefore - $beforeColumn = 'A'; - $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + /** + * Update single cell reference + * + * @param string $pCellReference Single cell reference + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell reference + * @throws Exception + */ + private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); // Get coordinates - $newColumn = 'A'; - $newRow = 1; + $newColumn = 'A'; + $newRow = 1; list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); // Make sure the reference can be used @@ -520,20 +540,20 @@ class PHPExcel_ReferenceHelper // Create new column reference if ($updateColumn) { - $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); + $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); } // Create new row reference if ($updateRow) { - $newRow = $newRow + $pNumRows; + $newRow = $newRow + $pNumRows; } // Return new reference return $newColumn . $newRow; - } else { - throw new Exception("Only single cell references may be passed to this method."); - } - } + } else { + throw new Exception("Only single cell references may be passed to this method."); + } + } /** * __clone implementation. Cloning should not be allowed in a Singleton! diff --git a/libraries/PHPExcel/PHPExcel/RichText.php b/libraries/PHPExcel/PHPExcel/RichText.php index ad78f112b..aca7796ea 100644 --- a/libraries/PHPExcel/PHPExcel/RichText.php +++ b/libraries/PHPExcel/PHPExcel/RichText.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -60,7 +60,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText implements PHPExcel_IComparable { @@ -157,7 +157,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable // Return value $returnValue = ''; - // Loop trough all PHPExcel_RichText_ITextElement + // Loop through all PHPExcel_RichText_ITextElement foreach ($this->_richTextElements as $text) { $returnValue .= $text->getText(); } @@ -257,37 +257,6 @@ class PHPExcel_RichText implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php b/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php index 32948f79e..713a522c0 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php +++ b/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -41,7 +41,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_RichText_ITextElement { diff --git a/libraries/PHPExcel/PHPExcel/RichText/Run.php b/libraries/PHPExcel/PHPExcel/RichText/Run.php index e1297fcdd..82aff89c8 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/Run.php +++ b/libraries/PHPExcel/PHPExcel/RichText/Run.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -47,7 +47,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement { diff --git a/libraries/PHPExcel/PHPExcel/RichText/TextElement.php b/libraries/PHPExcel/PHPExcel/RichText/TextElement.php index 11b7cf120..d16a92995 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/TextElement.php +++ b/libraries/PHPExcel/PHPExcel/RichText/TextElement.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -44,7 +44,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Date.php b/libraries/PHPExcel/PHPExcel/Shared/Date.php index f5e2ec8c2..dbb5be1eb 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Date.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Date.php @@ -3,7 +3,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,9 +21,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -47,7 +47,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Date { @@ -106,12 +106,15 @@ class PHPExcel_Shared_Date // Perform conversion if ($dateValue >= 1) { $utcDays = $dateValue - $myExcelBaseDate; - $returnValue = (integer) round($utcDays * 24 * 60 * 60); + $returnValue = round($utcDays * 24 * 60 * 60); + if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) { + $returnValue = (integer) $returnValue; + } } else { $hours = round($dateValue * 24); $mins = round($dateValue * 24 * 60) - round($hours * 60); $secs = round($dateValue * 24 * 60 * 60) - round($hours * 60 * 60) - round($mins * 60); - $returnValue = (integer) mktime($hours, $mins, $secs); + $returnValue = (integer) gmmktime($hours, $mins, $secs); } // Return @@ -132,8 +135,10 @@ class PHPExcel_Shared_Date $hours = round($time / 3600); $minutes = round($time / 60) - ($hours * 60); $seconds = round($time) - ($hours * 3600) - ($minutes * 60); + $dateObj = date_create('1-Jan-1970+'.$days.' days'); $dateObj->setTime($hours,$minutes,$seconds); + return $dateObj; } // function ExcelToPHPObject() diff --git a/libraries/PHPExcel/PHPExcel/Shared/Drawing.php b/libraries/PHPExcel/PHPExcel/Shared/Drawing.php index b56bbfd76..c2ad33df0 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,18 +20,30 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ +/** PHPExcel root */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); +} + +/** PHPExcel_Shared_String */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; + + /** * PHPExcel_Shared_Drawing * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Drawing { @@ -60,33 +72,67 @@ class PHPExcel_Shared_Drawing } /** - * Convert pixels to cell dimension. Exact algorithm not known. + * Convert pixels to column width. Exact algorithm not known. * By inspection of a real Excel file using Calibri 11, one finds 1000px ~ 142.85546875 * This gives a conversion factor of 7. Also, we assume that pixels and font size are proportional. * * @param int $pValue Value in pixels - * @param int $pFontSize Default font size of workbook + * @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook * @return int Value in cell dimension */ - public static function pixelsToCellDimension($pValue = 0, $pFontSize = 11) { - return $pValue * $pFontSize / 11 / 7; - } - - /** - * Convert cell width to pixels - * - * @param int $pValue Value in cell dimension - * @param int $pFontSize Default font size of workbook - * @return int Value in pixels - */ - public static function cellDimensionToPixels($pValue = 0, $pFontSize = 11) { - if ($pValue != 0) { - return $pValue * 7 * $pFontSize / 11; + public static function pixelsToCellDimension($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { + // Font name and size + $name = $pDefaultFont->getName(); + $size = $pDefaultFont->getSize(); + + if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { + // Exact width can be determined + $colWidth = $pValue + * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width'] + / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px']; } else { - return 0; + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $colWidth = $pValue * 11 + * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] + / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] / $size; } + + return $colWidth; } - + + /** + * Convert column width from (intrinsic) Excel units to pixels + * + * @param float $pValue Value in cell dimension + * @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook + * @return int Value in pixels + */ + public static function cellDimensionToPixels($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { + // Font name and size + $name = $pDefaultFont->getName(); + $size = $pDefaultFont->getSize(); + + if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { + // Exact width can be determined + $colWidth = $pValue + * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px'] + / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width']; + + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $colWidth = $pValue * $size + * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] + / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] / 11; + } + + // Round pixels to closest integer + $colWidth = (int) round($colWidth); + + return $colWidth; + } + /** * Convert pixels to points * diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher.php b/libraries/PHPExcel/PHPExcel/Shared/Escher.php index f0244eb60..4ed04b384 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php index 1084d94f6..243dab350 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php index 846b56990..8f07e52ae 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php index 481e7db55..952685307 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php index cdbdde01f..5883ae26b 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php index 4209b424c..c15995a63 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php index e472b218c..0ae494851 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php index d835a0687..87609cca7 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Excel5.php b/libraries/PHPExcel/PHPExcel/Shared/Excel5.php index b8e2050ee..f9b3f818a 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ @@ -39,12 +39,15 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; /** PHPExcel_Shared_Drawing */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; +/** PHPExcel_Shared_Font */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; + /** * PHPExcel_Shared_Excel5 * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Excel5 { @@ -59,8 +62,8 @@ class PHPExcel_Shared_Excel5 */ public static function sizeCol($sheet, $col = 'A') { - // default font size of workbook - $fontSize = $sheet->getParent()->getDefaultStyle()->getFont()->getSize(); + // default font of the workbook + $font = $sheet->getParent()->getDefaultStyle()->getFont(); $columnDimensions = $sheet->getColumnDimensions(); @@ -70,17 +73,19 @@ class PHPExcel_Shared_Excel5 // then we have column dimension with explicit width $columnDimension = $columnDimensions[$col]; $width = $columnDimension->getWidth(); - $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $fontSize); + $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); } else if ($sheet->getDefaultColumnDimension()->getWidth() != -1) { // then we have default column dimension with explicit width $defaultColumnDimension = $sheet->getDefaultColumnDimension(); $width = $defaultColumnDimension->getWidth(); - $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $fontSize); + $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); } else { - $pixelWidth = (int) 64 * $fontSize / 11; // here we interpolate from Calibri 11 + + // we don't even have any default column dimension. Width depends on default font + $pixelWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($font, true); } // now find the effective column width in pixels @@ -104,6 +109,9 @@ class PHPExcel_Shared_Excel5 */ public static function sizeRow($sheet, $row = 1) { + // default font of the workbook + $font = $sheet->getParent()->getDefaultStyle()->getFont(); + $rowDimensions = $sheet->getRowDimensions(); // first find the true row height in pixels (uncollapsed and unhidden) @@ -122,7 +130,11 @@ class PHPExcel_Shared_Excel5 $pixelRowHeight = PHPExcel_Shared_Drawing::pointsToPixels($rowHeight); } else { - $pixelRowHeight = 20; // here we assume Calibri 11 + + // we don't even have any default row dimension. Height depends on default font + $pointRowHeight = PHPExcel_Shared_Font::getDefaultRowHeightByFont($font); + $pixelRowHeight = PHPExcel_Shared_Font::fontSizeToPixels($pointRowHeight); + } // now find the effective row height in pixels @@ -301,8 +313,8 @@ class PHPExcel_Shared_Excel5 // Convert the pixel values to the percentage value expected by Excel $x1 = $x1 / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; $y1 = $y1 / self::sizeRow($sheet, $row_start + 1) * 256; - $x2 = $width / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object - $y2 = $height / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object + $x2 = ($width + 1) / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object + $y2 = ($height + 1) / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object $startCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_start) . ($row_start + 1); $endCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_end) . ($row_end + 1); diff --git a/libraries/PHPExcel/PHPExcel/Shared/File.php b/libraries/PHPExcel/PHPExcel/Shared/File.php index 3c24520a9..a742d152f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/File.php +++ b/libraries/PHPExcel/PHPExcel/Shared/File.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_File { @@ -79,7 +79,7 @@ class PHPExcel_Shared_File // Found something? if ($returnValue == '' || is_null($returnValue)) { - $pathArray = split('/' , $pFilename); + $pathArray = explode('/' , $pFilename); while(in_array('..', $pathArray) && $pathArray[0] != '..') { for ($i = 0; $i < count($pathArray); ++$i) { if ($pathArray[$i] == '..' && $i > 0) { @@ -95,4 +95,42 @@ class PHPExcel_Shared_File // Return return $returnValue; } + + /** + * Get the systems temporary directory. + * + * @return string + */ + public static function sys_get_temp_dir() + { + // sys_get_temp_dir is only available since PHP 5.2.1 + // http://php.net/manual/en/function.sys-get-temp-dir.php#94119 + + if ( !function_exists('sys_get_temp_dir')) { + if( $temp = getenv('TMP') ) { + return realpath($temp); + } + if( $temp = getenv('TEMP') ) { + return realpath($temp); + } + if( $temp = getenv('TMPDIR') ) { + return realpath($temp); + } + + // trick for creating a file in system's temporary dir + // without knowing the path of the system's temporary dir + $temp = tempnam(__FILE__, ''); + if (file_exists($temp)) { + unlink($temp); + return realpath(dirname($temp)); + } + + return null; + + } + + // use ordinary built-in PHP function + return realpath(sys_get_temp_dir()); + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/Font.php b/libraries/PHPExcel/PHPExcel/Shared/Font.php index 9bc8484fa..8bf67d5b3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Font.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,21 +20,37 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ +/** PHPExcel root */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); +} + +/** PHPExcel_Shared_String */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; + + /** * PHPExcel_Shared_Font * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Font { + /* Methods for resolving autosize value */ + const AUTOSIZE_METHOD_APPROX = 'approx'; + const AUTOSIZE_METHOD_EXACT = 'exact'; + /** Character set codes used by BIFF5-8 in Font records */ const CHARSET_ANSI_LATIN = 0x00; const CHARSET_SYSTEM_DEFAULT = 0x01; @@ -56,6 +72,175 @@ class PHPExcel_Shared_Font const CHARSET_ANSI_LATIN_II = 0xEE; const CHARSET_OEM_LATIN_I = 0xFF; + // XXX: Constants created! + /** Font filenames */ + const ARIAL = 'arial.ttf'; + const ARIAL_BOLD = 'arialbd.ttf'; + const ARIAL_ITALIC = 'ariali.ttf'; + const ARIAL_BOLD_ITALIC = 'arialbi.ttf'; + + const CALIBRI = 'CALIBRI.TTF'; + const CALIBRI_BOLD = 'CALIBRIB.TTF'; + const CALIBRI_ITALIC = 'CALIBRII.TTF'; + const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF'; + + const COMIC_SANS_MS = 'comic.ttf'; + const COMIC_SANS_MS_BOLD = 'comicbd.ttf'; + + const COURIER_NEW = 'cour.ttf'; + const COURIER_NEW_BOLD = 'courbd.ttf'; + const COURIER_NEW_ITALIC = 'couri.ttf'; + const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf'; + + const GEORGIA = 'georgia.ttf'; + const GEORGIA_BOLD = 'georgiab.ttf'; + const GEORGIA_ITALIC = 'georgiai.ttf'; + const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf'; + + const IMPACT = 'impact.ttf'; + + const LIBERATION_SANS = 'LiberationSans-Regular.ttf'; + const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf'; + const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf'; + const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf'; + + const LUCIDA_CONSOLE = 'lucon.ttf'; + const LUCIDA_SANS_UNICODE = 'l_10646.ttf'; + + const MICROSOFT_SANS_SERIF = 'micross.ttf'; + + const PALATINO_LINOTYPE = 'pala.ttf'; + const PALATINO_LINOTYPE_BOLD = 'palab.ttf'; + const PALATINO_LINOTYPE_ITALIC = 'palai.ttf'; + const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf'; + + const SYMBOL = 'symbol.ttf'; + + const TAHOMA = 'tahoma.ttf'; + const TAHOMA_BOLD = 'tahomabd.ttf'; + + const TIMES_NEW_ROMAN = 'times.ttf'; + const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf'; + const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf'; + const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf'; + + const TREBUCHET_MS = 'trebuc.ttf'; + const TREBUCHET_MS_BOLD = 'trebucbd.ttf'; + const TREBUCHET_MS_ITALIC = 'trebucit.ttf'; + const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf'; + + const VERDANA = 'verdana.ttf'; + const VERDANA_BOLD = 'verdanab.ttf'; + const VERDANA_ITALIC = 'verdanai.ttf'; + const VERDANA_BOLD_ITALIC = 'verdanaz.ttf'; + + /** + * AutoSize method + * + * @var string + */ + private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX; + + /** + * Path to folder containing TrueType font .ttf files + * + * @var string + */ + private static $trueTypeFontPath = null; + + /** + * How wide is a default column for a given default font and size? + * Empirical data found by inspecting real Excel files and reading off the pixel width + * in Microsoft Office Excel 2007. + * + * @var array + */ + public static $defaultColumnWidths = array( + 'Arial' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 56, 'width' => 9.33203125), + 9 => array('px' => 64, 'width' => 9.14062500), + 10 => array('px' => 64, 'width' => 9.14062500), + ), + 'Calibri' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 56, 'width' => 9.33203125), + 9 => array('px' => 56, 'width' => 9.33203125), + 10 => array('px' => 64, 'width' => 9.14062500), + 11 => array('px' => 64, 'width' => 9.14062500), + ), + 'Verdana' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 64, 'width' => 9.14062500), + 9 => array('px' => 72, 'width' => 9.00000000), + 10 => array('px' => 72, 'width' => 9.00000000), + ), + ); + + /** + * Set autoSize method + * + * @param string $pValue + */ + public static function setAutoSizeMethod($pValue = 'approx') + { + self::$autoSizeMethod = $pValue; + } + + /** + * Get autoSize method + * + * @return string + */ + public static function getAutoSizeMethod() + { + return self::$autoSizeMethod; + } + + /** + * Set the path to the folder containing .ttf files. There should be a trailing slash. + * Typical locations on variout some platforms: + *
    + *
  • C:/Windows/Fonts/
  • + *
  • /usr/share/fonts/truetype/
  • + *
  • ~/.fonts/
  • + *
+ * + * @param string $pValue + */ + public static function setTrueTypeFontPath($pValue = '') + { + self::$trueTypeFontPath = $pValue; + } + + /** + * Get the path to the folder containing .ttf files. + * + * @return string + */ + public static function getTrueTypeFontPath() + { + return self::$trueTypeFontPath; + } + /** * Calculate an (approximate) OpenXML column width, based on font size and text contained * @@ -65,29 +250,120 @@ class PHPExcel_Shared_Font * @param int $rotation Rotation angle * @return int Column width */ - public static function calculateColumnWidth($fontSize = 9, $fontSizeInPixels = false, $columnText = '', $rotation = 0) { - if (!$fontSizeInPixels) { - // Translate points size to pixel size - $fontSize = PHPExcel_Shared_Font::fontSizeToPixels($fontSize); - } - - // If it is rich text, use rich text... + public static function calculateColumnWidth(PHPExcel_Style_Font $font, $columnText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { + + // If it is rich text, use plain text if ($columnText instanceof PHPExcel_RichText) { $columnText = $columnText->getPlainText(); } - - // Only measure the part before the first newline character - if (strpos($columnText, "\r") !== false) { - $columnText = substr($columnText, 0, strpos($columnText, "\r")); - } + + // Only measure the part before the first newline character (is always "\n") if (strpos($columnText, "\n") !== false) { $columnText = substr($columnText, 0, strpos($columnText, "\n")); } + + // Try to get the exact text width in pixels + try { + // If autosize method is set to 'approx', use approximation + if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) { + throw new Exception('AutoSize method is set to approx'); + } + + // Width of text in pixels excl. padding + $columnWidth = self::getTextWidthPixelsExact($columnText, $font, $rotation); + + // Excel adds some padding, use 1.07 of the width of an 'n' glyph + $columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding + + } catch (Exception $e) { + // Width of text in pixels excl. padding, approximation + $columnWidth = self::getTextWidthPixelsApprox($columnText, $font, $rotation); + + // Excel adds some padding, just use approx width of 'n' glyph + $columnWidth += self::getTextWidthPixelsApprox('n', $font, 0); + } + + // Convert from pixel width to column width + $columnWidth = PHPExcel_Shared_Drawing::pixelsToCellDimension($columnWidth, $defaultFont); + + // Return + return round($columnWidth, 6); + } + + /** + * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle + * + * @param string $text + * @param PHPExcel_Style_Font + * @param int $rotation + * @return int + * @throws Exception + */ + public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) { + if (!function_exists('imagettfbbox')) { + throw new Exception('GD library needs to be enabled'); + } + + // font size should really be supplied in pixels in GD2, + // but since GD2 seems to assume 72dpi, pixels and points are the same + $fontFile = self::getTrueTypeFontFileFromFont($font); + $textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text); + + // Get corners positions + $lowerLeftCornerX = $textBox[0]; + $lowerLeftCornerY = $textBox[1]; + $lowerRightCornerX = $textBox[2]; + $lowerRightCornerY = $textBox[3]; + $upperRightCornerX = $textBox[4]; + $upperRightCornerY = $textBox[5]; + $upperLeftCornerX = $textBox[6]; + $upperLeftCornerY = $textBox[7]; - // Calculate column width - // values 1.025 and 0.584 found via interpolation by inspecting real Excel files with - // Calibri font. May need further adjustment - $columnWidth = 1.025 * strlen($columnText) + 0.584; // Excel adds some padding + // Consider the rotation when calculating the width + $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); + + return $textWidth; + } + + /** + * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle + * + * @param string $columnText + * @param PHPExcel_Style_Font $font + * @param int $rotation + * @return int Text width in pixels (no padding added) + */ + public static function getTextWidthPixelsApprox($columnText, PHPExcel_Style_Font $font = null, $rotation = 0) + { + $fontName = $font->getName(); + $fontSize = $font->getSize(); + + // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. + switch ($fontName) { + case 'Calibri': + // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. + $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + break; + + case 'Arial': + // value 7 was found via interpolation by inspecting real Excel files with Arial 10 font. + $columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size + break; + + case 'Verdana': + // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. + $columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size + break; + + default: + // just assume Calibri + $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + break; + } // Calculate approximate rotated column width if ($rotation !== 0) { @@ -101,18 +377,19 @@ class PHPExcel_Shared_Font } } - // Return - return round($columnWidth, 6); + // pixel width is an integer + $columnWidth = (int) $columnWidth; + return $columnWidth; } - + /** * Calculate an (approximate) pixel size, based on a font points size * * @param int $fontSizeInPoints Font size (in points) * @return int Font size (in pixels) */ - public static function fontSizeToPixels($fontSizeInPoints = 12) { - return ((16 / 12) * $fontSizeInPoints); + public static function fontSizeToPixels($fontSizeInPoints = 11) { + return (int) ((4 / 3) * $fontSizeInPoints); } /** @@ -135,6 +412,133 @@ class PHPExcel_Shared_Font return ($sizeInCm * 37.795275591); } + /** + * Returns the font path given the font + * + * @param PHPExcel_Style_Font + * @return string Path to TrueType font file + */ + public static function getTrueTypeFontFileFromFont($font) { + if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) { + throw new Exception('Valid directory to TrueType Font files not specified'); + } + + $name = $font->getName(); + $bold = $font->getBold(); + $italic = $font->getItalic(); + + // Check if we can map font to true type font file + switch ($name) { + case 'Arial': + $fontFile = ( + $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD) + : ($italic ? self::ARIAL_ITALIC : self::ARIAL) + ); + break; + + case 'Calibri': + $fontFile = ( + $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD) + : ($italic ? self::CALIBRI_ITALIC : self::CALIBRI) + ); + break; + + case 'Courier New': + $fontFile = ( + $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD) + : ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW) + ); + break; + + case 'Comic Sans MS': + $fontFile = ( + $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS + ); + break; + + case 'Georgia': + $fontFile = ( + $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD) + : ($italic ? self::GEORGIA_ITALIC : self::GEORGIA) + ); + break; + + case 'Impact': + $fontFile = self::IMPACT; + break; + + case 'Liberation Sans': + $fontFile = ( + $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD) + : ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS) + ); + break; + + case 'Lucida Console': + $fontFile = self::LUCIDA_CONSOLE; + break; + + case 'Lucida Sans Unicode': + $fontFile = self::LUCIDA_SANS_UNICODE; + break; + + case 'Microsoft Sans Serif': + $fontFile = self::MICROSOFT_SANS_SERIF; + break; + + case 'Palatino Linotype': + $fontFile = ( + $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD) + : ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE) + ); + break; + + case 'Symbol': + $fontFile = self::SYMBOL; + break; + + case 'Tahoma': + $fontFile = ( + $bold ? self::TAHOMA_BOLD : self::TAHOMA + ); + break; + + case 'Times New Roman': + $fontFile = ( + $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD) + : ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN) + ); + break; + + case 'Trebuchet MS': + $fontFile = ( + $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD) + : ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS) + ); + break; + + case 'Verdana': + $fontFile = ( + $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD) + : ($italic ? self::VERDANA_ITALIC : self::VERDANA) + ); + break; + + default: + throw new Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file'); + break; + } + + $fontFile = self::$trueTypeFontPath . $fontFile; + + // Check if file actually exists + if (!file_exists($fontFile)) { + throw New Exception('TrueType Font file not found'); + } + + return $fontFile; + } + /** * Returns the associated charset for the font name. * @@ -145,6 +549,7 @@ class PHPExcel_Shared_Font { switch ($name) { // Add more cases. Check FONT records in real Excel files. + case 'EucrosiaUPC': return self::CHARSET_ANSI_THAI; case 'Wingdings': return self::CHARSET_SYMBOL; case 'Wingdings 2': return self::CHARSET_SYMBOL; case 'Wingdings 3': return self::CHARSET_SYMBOL; @@ -152,4 +557,214 @@ class PHPExcel_Shared_Font } } + /** + * Get the effective column width for columns without a column dimension or column with width -1 + * For example, for Calibri 11 this is 9.140625 (64 px) + * + * @param PHPExcel_Style_Font $font The workbooks default font + * @param boolean $pPixels true = return column width in pixels, false = return in OOXML units + * @return mixed Column width + */ + public static function getDefaultColumnWidthByFont(PHPExcel_Style_Font $font, $pPixels = false) + { + if (isset(self::$defaultColumnWidths[$font->getName()][$font->getSize()])) { + // Exact width can be determined + $columnWidth = $pPixels ? + self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px'] + : self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width']; + + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $columnWidth = $pPixels ? + self::$defaultColumnWidths['Calibri'][11]['px'] + : self::$defaultColumnWidths['Calibri'][11]['width']; + $columnWidth = $columnWidth * $font->getSize() / 11; + + // Round pixels to closest integer + if ($pPixels) { + $columnWidth = (int) round($columnWidth); + } + } + + return $columnWidth; + } + + /** + * Get the effective row height for rows without a row dimension or rows with height -1 + * For example, for Calibri 11 this is 15 points + * + * @param PHPExcel_Style_Font $font The workbooks default font + * @return float Row height in points + */ + public static function getDefaultRowHeightByFont(PHPExcel_Style_Font $font) + { + switch ($font->getName()) { + case 'Arial': + switch ($font->getSize()) { + case 10: + // inspection of Arial 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Arial 9 workbook says 12.00pt ~16px + $rowHeight = 12; + break; + + case 8: + // inspection of Arial 8 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 7: + // inspection of Arial 7 workbook says 9.00pt ~12px + $rowHeight = 9; + break; + + case 6: + case 5: + // inspection of Arial 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Arial 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Arial 3 workbook says 6.00pt ~8px + $rowHeight = 6; + break; + + case 2: + case 1: + // inspection of Arial 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Arial 10 workbook as an approximation, extrapolation + $rowHeight = 12.75 * $font->getSize() / 10; + break; + } + break; + + case 'Calibri': + switch ($font->getSize()) { + case 11: + // inspection of Calibri 11 workbook says 15.00pt ~20px + $rowHeight = 15; + break; + + case 10: + // inspection of Calibri 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Calibri 9 workbook says 12.00pt ~16px + $rowHeight = 12; + break; + + case 8: + // inspection of Calibri 8 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 7: + // inspection of Calibri 7 workbook says 9.00pt ~12px + $rowHeight = 9; + break; + + case 6: + case 5: + // inspection of Calibri 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Calibri 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Calibri 3 workbook says 6.00pt ~8px + $rowHeight = 6.00; + break; + + case 2: + case 1: + // inspection of Calibri 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Calibri 11 workbook as an approximation, extrapolation + $rowHeight = 15 * $font->getSize() / 11; + break; + } + break; + + case 'Verdana': + switch ($font->getSize()) { + case 10: + // inspection of Verdana 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Verdana 9 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 8: + // inspection of Verdana 8 workbook says 10.50pt ~14px + $rowHeight = 10.50; + break; + + case 7: + // inspection of Verdana 7 workbook says 9.00pt ~12px + $rowHeight = 9.00; + break; + + case 6: + case 5: + // inspection of Verdana 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Verdana 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Verdana 3 workbook says 6.00pt ~8px + $rowHeight = 6; + break; + + case 2: + case 1: + // inspection of Verdana 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Verdana 10 workbook as an approximation, extrapolation + $rowHeight = 12.75 * $font->getSize() / 10; + break; + } + break; + + default: + // just use Calibri as an approximation + $rowHeight = 15 * $font->getSize() / 11; + break; + } + + return $rowHeight; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php index efababbc4..49659d03c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php @@ -21,6 +21,8 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/LUDecomposition.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/QRDecomposition.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/EigenvalueDecomposition.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/SingularValueDecomposition.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; /* * Matrix class @@ -760,7 +762,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] += $M->get($i, $j); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] += $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; @@ -832,7 +848,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] -= $M->get($i, $j); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] -= $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; @@ -906,7 +936,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] *= $M->get($i, $j); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] *= $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; @@ -943,7 +987,26 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $M->set($i, $j, $this->A[$i][$j] / $M->get($i, $j)); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + if ($value == 0) { + // Trap for Divide by Zero error + $M->set($i, $j, '#DIV/0!'); + } else { + $M->set($i, $j, $this->A[$i][$j] / $value); + } + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $M; @@ -1181,7 +1244,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] = pow($this->A[$i][$j],$M->get($i, $j)); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] = pow($this->A[$i][$j],$value); + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php index f9673f071..df96995c8 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (C) 2006 - 2009 PHPExcel + * Copyright (C) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_OLE * @copyright Copyright (c) 2006 - 2007 Christian Schmidt * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php index fd4bc947b..3cf1d1bd3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php @@ -248,7 +248,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS . pack("V", 0) . pack("V", 0x1000) . pack("V", $iSBDcnt ? 0 : -2) //Small Block Depot - . pack("V", 1) + . pack("V", $iSBDcnt) ); // Extra BDList Start, Count if ($iBdCnt < $i1stBdL) { diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLERead.php b/libraries/PHPExcel/PHPExcel/Shared/OLERead.php index 6ccaab9b8..46cb5ade3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLERead.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLERead.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); diff --git a/libraries/PHPExcel/PHPExcel/Shared/PDF.php b/libraries/PHPExcel/PHPExcel/Shared/PDF.php index 8d1416054..b66e8e0c1 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/PDF.php +++ b/libraries/PHPExcel/PHPExcel/Shared/PDF.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php b/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php index e8d11510b..1a5c11a33 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php +++ b/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_PasswordHasher { diff --git a/libraries/PHPExcel/PHPExcel/Shared/String.php b/libraries/PHPExcel/PHPExcel/Shared/String.php index 8a105f014..e165fdd63 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/String.php +++ b/libraries/PHPExcel/PHPExcel/Shared/String.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,10 +31,16 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_String { + /** Constants */ + /** Regular Expressions */ + // Fraction + const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)'; + + /** * Control characters array * @@ -42,6 +48,20 @@ class PHPExcel_Shared_String */ private static $_controlCharacters = array(); + /** + * Decimal separator + * + * @var string + */ + private static $_decimalSeparator; + + /** + * Thousands separator + * + * @var string + */ + private static $_thousandsSeparator; + /** * Is mbstring extension avalable? * @@ -60,7 +80,7 @@ class PHPExcel_Shared_String * Build control characters array */ private static function _buildControlCharacters() { - for ($i = 0; $i <= 19; ++$i) { + for ($i = 0; $i <= 31; ++$i) { if ($i != 9 && $i != 10 && $i != 13) { $find = '_x' . sprintf('%04s' , strtoupper(dechex($i))) . '_'; $replace = chr($i); @@ -97,12 +117,19 @@ class PHPExcel_Shared_String return self::$_isIconvEnabled; } - // IBM AIX iconv() does not work - self::$_isIconvEnabled = function_exists('iconv') && - !(defined('PHP_OS') && @stristr(PHP_OS, 'AIX') && defined('ICONV_IMPL') - && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && defined('ICONV_VERSION') - && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) ? - true : false; + // Check that iconv exists + // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false, + // we cannot use iconv when that happens + // Also, sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 + // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) + if (function_exists('iconv') + && @iconv('UTF-8', 'UTF-16LE', 'x') + && @iconv_substr('A', 0, 1, 'UTF-8') ) { + + self::$_isIconvEnabled = true; + } else { + self::$_isIconvEnabled = false; + } return self::$_isIconvEnabled; } @@ -172,7 +199,7 @@ class PHPExcel_Shared_String // else, no conversion return $value; } - + /** * Check if a string contains UTF8 data * @@ -213,7 +240,7 @@ class PHPExcel_Shared_String $ln = self::CountCharacters($value, 'UTF-8'); // option flags - $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? + $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? 0x0001 : 0x0000; // characters @@ -239,7 +266,7 @@ class PHPExcel_Shared_String $ln = self::CountCharacters($value, 'UTF-8'); // option flags - $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? + $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? 0x0001 : 0x0000; // characters @@ -272,7 +299,7 @@ class PHPExcel_Shared_String // else, no conversion return $value; } - + /** * Get character count. First try mbstring, then iconv, finally strlen * @@ -322,4 +349,82 @@ class PHPExcel_Shared_String return $string; } + + /** + * Identify whether a string contains a fractional numeric value, + * and convert it to a numeric if it is + * + * @param string &$operand string value to test + * @return boolean + */ + public static function convertToNumberIfFraction(&$operand) { + if (preg_match('/^'.self::STRING_REGEXP_FRACTION.'$/i', $operand, $match)) { + $sign = ($match[1] == '-') ? '-' : '+'; + $fractionFormula = '='.$sign.$match[2].$sign.$match[3]; + $operand = PHPExcel_Calculation::getInstance()->_calculateFormulaValue($fractionFormula); + return true; + } + return false; + } // function convertToNumberIfFraction() + + /** + * Get the decimal separator. If it has not yet been set explicitly, try to obtain number + * formatting information from locale. + * + * @return string + */ + public static function getDecimalSeparator() + { + if (!isset(self::$_decimalSeparator)) { + $localeconv = localeconv(); + self::$_decimalSeparator = $localeconv['decimal_point'] != '' + ? $localeconv['decimal_point'] : $localeconv['mon_decimal_point']; + + if (self::$_decimalSeparator == '') + { + // Default to . + self::$_decimalSeparator = '.'; + } + } + return self::$_decimalSeparator; + } + + /** + * Set the decimal separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for decimal separator + */ + public static function setDecimalSeparator($pValue = '.') + { + self::$_decimalSeparator = $pValue; + } + + /** + * Get the thousands separator. If it has not yet been set explicitly, try to obtain number + * formatting information from locale. + * + * @return string + */ + public static function getThousandsSeparator() + { + if (!isset(self::$_thousandsSeparator)) { + $localeconv = localeconv(); + self::$_thousandsSeparator = $localeconv['thousands_sep'] != '' + ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep']; + } + return self::$_thousandsSeparator; + } + + /** + * Set the thousands separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for thousands separator + */ + public static function setThousandsSeparator($pValue = ',') + { + self::$_thousandsSeparator = $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php b/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php index 9600a731d..4cd3d726a 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php +++ b/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ if (!defined('DATE_W3C')) { @@ -34,7 +34,7 @@ if (!defined('DATE_W3C')) { * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_XMLWriter { /** Temporary storage method */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php b/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php index ebcfcb00f..b5bc1cb02 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php +++ b/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -35,7 +35,7 @@ PHPExcel_Shared_ZipStreamWrapper::register(); * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_ZipStreamWrapper { /** @@ -84,7 +84,7 @@ class PHPExcel_Shared_ZipStreamWrapper { } // Parse URL - $url = @parse_url($path); + $url = @parse_url(str_replace('zip://', 'file://', $path)); // Fix URL if (!is_array($url)) { diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php index 00791da84..bd96d5827 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Best_Fit { @@ -239,7 +239,11 @@ class PHPExcel_Best_Fit $this->_SSResiduals = $SSres; $this->_DFResiduals = $this->_valueCount - 1 - $const; - $this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals); + if ($this->_DFResiduals == 0.0) { + $this->_stdevOfResiduals = 0.0; + } else { + $this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals); + } if (($SStot == 0.0) || ($SSres == $SStot)) { $this->_goodnessOfFit = 1; } else { @@ -252,9 +256,17 @@ class PHPExcel_Best_Fit $this->_slopeSE = $this->_stdevOfResiduals / sqrt($SSsex); $this->_intersectSE = $this->_stdevOfResiduals * sqrt(1 / ($this->_valueCount - ($sumX * $sumX) / $sumX2)); if ($this->_SSResiduals != 0.0) { - $this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals); + if ($this->_DFResiduals == 0.0) { + $this->_F = 0.0; + } else { + $this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals); + } } else { - $this->_F = $this->_SSRegression / $this->_DFResiduals; + if ($this->_DFResiduals == 0.0) { + $this->_F = 0.0; + } else { + $this->_F = $this->_SSRegression / $this->_DFResiduals; + } } } // function _calculateGoodnessOfFit() diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php index 498c47050..1d7212d9d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit { @@ -84,8 +84,14 @@ class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit private function _exponential_regression($yValues, $xValues, $const) { - $mArray = $xValues; - $yValues = array_map('log',$yValues); + foreach($yValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); $this->_leastSquareFit($yValues, $xValues, $const); } // function _exponential_regression() diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php index 2808fb4f3..265048196 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Linear_Best_Fit extends PHPExcel_Best_Fit { diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php index ba28dd833..115c78d0d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit { @@ -68,8 +68,14 @@ class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit private function _logarithmic_regression($yValues, $xValues, $const) { - $mArray = $xValues; - $xValues = array_map('log',$xValues); + foreach($xValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); $this->_leastSquareFit($yValues, $xValues, $const); } // function _logarithmic_regression() diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php index 65b8eee69..dca14ff3c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit { diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php index 2a1b10c1f..651aec2fe 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit { @@ -76,10 +76,22 @@ class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit private function _power_regression($yValues, $xValues, $const) { - $mArray = $xValues; - sort($mArray,SORT_NUMERIC); - $xValues = array_map('log',$xValues); - $yValues = array_map('log',$yValues); + foreach($xValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); + foreach($yValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); $this->_leastSquareFit($yValues, $xValues, $const); } // function _power_regression() diff --git a/libraries/PHPExcel/PHPExcel/Style.php b/libraries/PHPExcel/PHPExcel/Style.php index 874747749..5636df48f 100644 --- a/libraries/PHPExcel/PHPExcel/Style.php +++ b/libraries/PHPExcel/PHPExcel/Style.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -66,7 +66,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style implements PHPExcel_IComparable { @@ -201,7 +201,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getSharedComponent() { $activeSheet = $this->getActiveSheet(); - $selectedCell = $this->getXActiveCell(); // e.g. 'A1' + $selectedCell = $this->getActiveCell(); // e.g. 'A1' if ($activeSheet->cellExists($selectedCell)) { $cell = $activeSheet->getCell($selectedCell); @@ -230,9 +230,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->_parent->getActiveSheet()->getXSelectedCells(); + return $this->_parent->getActiveSheet()->getSelectedCells(); } /** @@ -241,9 +241,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->_parent->getActiveSheet()->getXActiveCell(); + return $this->_parent->getActiveSheet()->getActiveCell(); } /** @@ -299,204 +299,253 @@ class PHPExcel_Style implements PHPExcel_IComparable if (is_array($pStyles)) { if ($this->_isSupervisor) { - $pRange = $this->getXSelectedCells(); + $pRange = $this->getSelectedCells(); - if (is_array($pStyles)) { - // Uppercase coordinate - $pRange = strtoupper($pRange); - - // Is it a cell range or a single cell? - $rangeA = ''; - $rangeB = ''; - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } - - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } - - // Advanced mode - if ($pAdvanced && isset($pStyles['borders'])) { - - // 'allborders' is a shorthand property for 'outline' and 'inside' and - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['allborders'])) { - foreach (array('outline', 'inside') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['allborders']; - } - } - unset($pStyles['borders']['allborders']); // not needed any more - } - - // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['outline'])) { - foreach (array('top', 'right', 'bottom', 'left') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['outline']; - } - } - unset($pStyles['borders']['outline']); // not needed any more - } - - // 'inside' is a shorthand property for 'vertical' and 'horizontal' - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['inside'])) { - foreach (array('vertical', 'horizontal') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['inside']; - } - } - unset($pStyles['borders']['inside']); // not needed any more - } - - // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) - $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); - $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); - - // loop through up to 3 x 3 = 9 regions - for ($x = 1; $x <= $xMax; ++$x) { - // start column index for region - $colStart = ($x == 3) ? - PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) - : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); - - // end column index for region - $colEnd = ($x == 1) ? - PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) - : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); - - for ($y = 1; $y <= $yMax; ++$y) { - - // which edges are touching the region - $edges = array(); - - // are we at left edge - if ($x == 1) { - $edges[] = 'left'; - } - - // are we at right edge - if ($x == $xMax) { - $edges[] = 'right'; - } - - // are we at top edge? - if ($y == 1) { - $edges[] = 'top'; - } - - // are we at bottom edge? - if ($y == $yMax) { - $edges[] = 'bottom'; - } - - // start row index for region - $rowStart = ($y == 3) ? - $rangeEnd[1] : $rangeStart[1] + $y - 1; - - // end row index for region - $rowEnd = ($y == 1) ? - $rangeStart[1] : $rangeEnd[1] - $yMax + $y; - - // build range for region - $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; - - // retrieve relevant style array for region - $regionStyles = $pStyles; - unset($regionStyles['borders']['inside']); - - // what are the inner edges of the region when looking at the selection - $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); - - // inner edges that are not touching the region should take the 'inside' border properties if they have been set - foreach ($innerEdges as $innerEdge) { - switch ($innerEdge) { - case 'top': - case 'bottom': - // should pick up 'horizontal' border property if set - if (isset($pStyles['borders']['horizontal'])) { - $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; - } else { - unset($regionStyles['borders'][$innerEdge]); - } - break; - case 'left': - case 'right': - // should pick up 'vertical' border property if set - if (isset($pStyles['borders']['vertical'])) { - $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; - } else { - unset($regionStyles['borders'][$innerEdge]); - } - break; - } - } - - // apply region style to region by calling applyFromArray() in simple mode - $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); - } - } - return; - } - - // Simple mode - - // First loop through cells to find out which styles are affected by this operation - $oldXfIndexes = array(); - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; - } - } - - // clone each of the affected styles, apply the style arrray, and add the new styles to the workbook - $workbook = $this->getActiveSheet()->getParent(); - foreach ($oldXfIndexes as $oldXfIndex => $dummy) { - $style = $workbook->getCellXfByIndex($oldXfIndex); - $newStyle = clone $style; - $newStyle->applyFromArray($pStyles); - - if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { - // there is already such cell Xf in our collection - $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); - } else { - // we don't have such a cell Xf, need to add - $workbook->addCellXf($newStyle); - $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); - } - } - - // Loop through cells again and update the XF index - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); - $oldXfIndex = $cell->getXfIndex(); - $cell->setXfIndex($newXfIndexes[$oldXfIndex]); - } - } + // Uppercase coordinate + $pRange = strtoupper($pRange); + // Is it a cell range or a single cell? + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; } else { - throw new Exception("Invalid style array passed."); + list($rangeA, $rangeB) = explode(':', $pRange); } - + + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // ADVANCED MODE: + + if ($pAdvanced && isset($pStyles['borders'])) { + + // 'allborders' is a shorthand property for 'outline' and 'inside' and + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['allborders'])) { + foreach (array('outline', 'inside') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['allborders']; + } + } + unset($pStyles['borders']['allborders']); // not needed any more + } + + // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['outline'])) { + foreach (array('top', 'right', 'bottom', 'left') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['outline']; + } + } + unset($pStyles['borders']['outline']); // not needed any more + } + + // 'inside' is a shorthand property for 'vertical' and 'horizontal' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['inside'])) { + foreach (array('vertical', 'horizontal') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['inside']; + } + } + unset($pStyles['borders']['inside']); // not needed any more + } + + // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) + $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); + $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); + + // loop through up to 3 x 3 = 9 regions + for ($x = 1; $x <= $xMax; ++$x) { + // start column index for region + $colStart = ($x == 3) ? + PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); + + // end column index for region + $colEnd = ($x == 1) ? + PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); + + for ($y = 1; $y <= $yMax; ++$y) { + + // which edges are touching the region + $edges = array(); + + // are we at left edge + if ($x == 1) { + $edges[] = 'left'; + } + + // are we at right edge + if ($x == $xMax) { + $edges[] = 'right'; + } + + // are we at top edge? + if ($y == 1) { + $edges[] = 'top'; + } + + // are we at bottom edge? + if ($y == $yMax) { + $edges[] = 'bottom'; + } + + // start row index for region + $rowStart = ($y == 3) ? + $rangeEnd[1] : $rangeStart[1] + $y - 1; + + // end row index for region + $rowEnd = ($y == 1) ? + $rangeStart[1] : $rangeEnd[1] - $yMax + $y; + + // build range for region + $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; + + // retrieve relevant style array for region + $regionStyles = $pStyles; + unset($regionStyles['borders']['inside']); + + // what are the inner edges of the region when looking at the selection + $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); + + // inner edges that are not touching the region should take the 'inside' border properties if they have been set + foreach ($innerEdges as $innerEdge) { + switch ($innerEdge) { + case 'top': + case 'bottom': + // should pick up 'horizontal' border property if set + if (isset($pStyles['borders']['horizontal'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + case 'left': + case 'right': + // should pick up 'vertical' border property if set + if (isset($pStyles['borders']['vertical'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + } + } + + // apply region style to region by calling applyFromArray() in simple mode + $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); + } + } + return; + } + + // SIMPLE MODE: + + // Selection type, inspect + if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) { + $selectionType = 'COLUMN'; + } else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) { + $selectionType = 'ROW'; + } else { + $selectionType = 'CELL'; + } + + // First loop through columns, rows, or cells to find out which styles are affected by this operation + switch ($selectionType) { + case 'COLUMN': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; + } + break; + + case 'ROW': + $oldXfIndexes = array(); + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) { + $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style + } else { + $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; + } + } + break; + + case 'CELL': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; + } + } + break; + } + + // clone each of the affected styles, apply the style arrray, and add the new styles to the workbook + $workbook = $this->getActiveSheet()->getParent(); + foreach ($oldXfIndexes as $oldXfIndex => $dummy) { + $style = $workbook->getCellXfByIndex($oldXfIndex); + $newStyle = clone $style; + $newStyle->applyFromArray($pStyles); + + if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { + // there is already such cell Xf in our collection + $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($newStyle); + $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); + } + } + + // Loop through columns, rows, or cells again and update the XF index + switch ($selectionType) { + case 'COLUMN': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col); + $oldXfIndex = $columnDimension->getXfIndex(); + $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; + + case 'ROW': + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $rowDimension = $this->getActiveSheet()->getRowDimension($row); + $oldXfIndex = $rowDimension->getXfIndex() === null ? + 0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style + $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; + + case 'CELL': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); + $oldXfIndex = $cell->getXfIndex(); + $cell->setXfIndex($newXfIndexes[$oldXfIndex]); + } + } + break; + } + } else { + // not a supervisor, just apply the style array directly on style object if (array_key_exists('fill', $pStyles)) { $this->getFill()->applyFromArray($pStyles['fill']); } @@ -585,7 +634,7 @@ class PHPExcel_Style implements PHPExcel_IComparable * @return PHPExcel_Style_Conditional[] */ public function getConditionalStyles() { - return $this->getActiveSheet()->getConditionalStyles($this->getXActiveCell()); + return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); } /** @@ -596,7 +645,7 @@ class PHPExcel_Style implements PHPExcel_IComparable */ public function setConditionalStyles($pValue = null) { if (is_array($pValue)) { - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($this->getXSelectedCells()) as $cellReference) { + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($this->getSelectedCells()) as $cellReference) { $this->getActiveSheet()->setConditionalStyles($cellReference, $pValue); } } @@ -635,37 +684,6 @@ class PHPExcel_Style implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Get own index in style collection * diff --git a/libraries/PHPExcel/PHPExcel/Style/Alignment.php b/libraries/PHPExcel/PHPExcel/Style/Alignment.php index 6958b6a8a..fa52e0869 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Alignment.php +++ b/libraries/PHPExcel/PHPExcel/Style/Alignment.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Alignment implements PHPExcel_IComparable { @@ -190,9 +190,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -201,9 +201,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -238,7 +238,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('horizontal', $pStyles)) { $this->setHorizontal($pStyles['horizontal']); @@ -290,7 +290,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('horizontal' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_horizontal = $pValue; @@ -323,7 +323,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('vertical' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_vertical = $pValue; } @@ -359,7 +359,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ( ($pValue >= -90 && $pValue <= 90) || $pValue == -165 ) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('rotation' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_textRotation = $pValue; } @@ -394,7 +394,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('wrap' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_wrapText = $pValue; } @@ -425,7 +425,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('shrinkToFit' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_shrinkToFit = $pValue; } @@ -458,7 +458,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('indent' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_indent = $pValue; } @@ -485,37 +485,6 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Border.php b/libraries/PHPExcel/PHPExcel/Style/Border.php index 2509d71c6..edaeaf301 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Border.php +++ b/libraries/PHPExcel/PHPExcel/Style/Border.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Border implements PHPExcel_IComparable { @@ -200,9 +200,9 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -211,9 +211,9 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -289,7 +289,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('style', $pStyles)) { $this->setBorderStyle($pStyles['style']); @@ -329,7 +329,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('style' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_borderStyle = $pValue; } @@ -358,7 +358,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_color = $color; } @@ -381,37 +381,6 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Borders.php b/libraries/PHPExcel/PHPExcel/Style/Borders.php index 7b6ae30b9..4a6b3460b 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Borders.php +++ b/libraries/PHPExcel/PHPExcel/Style/Borders.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Borders implements PHPExcel_IComparable { @@ -54,6 +54,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable const DIAGONAL_NONE = 0; const DIAGONAL_UP = 1; const DIAGONAL_DOWN = 2; + const DIAGONAL_BOTH = 3; /** * Left @@ -241,9 +242,9 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -252,9 +253,9 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -309,7 +310,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('left', $pStyles)) { $this->getLeft()->applyFromArray($pStyles['left']); @@ -470,7 +471,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('diagonaldirection' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_diagonalDirection = $pValue; } @@ -497,37 +498,6 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Color.php b/libraries/PHPExcel/PHPExcel/Style/Color.php index 22840cd65..e17595c0d 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Color.php +++ b/libraries/PHPExcel/PHPExcel/Style/Color.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Color implements PHPExcel_IComparable { @@ -171,9 +171,9 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -182,9 +182,9 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -226,7 +226,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('rgb', $pStyles)) { $this->setRGB($pStyles['rgb']); @@ -265,7 +265,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('argb' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_argb = $pValue; } @@ -296,7 +296,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('argb' => 'FF' . $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_argb = 'FF' . $pValue; } @@ -404,37 +404,6 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Conditional.php b/libraries/PHPExcel/PHPExcel/Style/Conditional.php index e389ec222..e0520c8ec 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Conditional.php +++ b/libraries/PHPExcel/PHPExcel/Style/Conditional.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Conditional implements PHPExcel_IComparable { @@ -276,37 +276,6 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Fill.php b/libraries/PHPExcel/PHPExcel/Style/Fill.php index 6875b31dc..2d5fbe102 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Fill.php +++ b/libraries/PHPExcel/PHPExcel/Style/Fill.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Fill implements PHPExcel_IComparable { @@ -192,9 +192,9 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -203,9 +203,9 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -244,7 +244,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('type', $pStyles)) { $this->setFillType($pStyles['type']); @@ -289,7 +289,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function setFillType($pValue = PHPExcel_Style_Fill::FILL_NONE) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('type' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_fillType = $pValue; } @@ -317,7 +317,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function setRotation($pValue = 0) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('rotation' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_rotation = $pValue; } @@ -346,7 +346,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStartColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_startColor = $color; } @@ -375,7 +375,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getEndColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_endColor = $color; } @@ -400,37 +400,6 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Font.php b/libraries/PHPExcel/PHPExcel/Style/Font.php index 1caa8be3b..2adaff11c 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Font.php +++ b/libraries/PHPExcel/PHPExcel/Style/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Font implements PHPExcel_IComparable { @@ -207,9 +207,9 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -218,9 +218,9 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -259,7 +259,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('name', $pStyles)) { $this->setName($pStyles['name']); @@ -319,7 +319,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('name' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_name = $pValue; } @@ -350,7 +350,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('size' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_size = $pValue; } @@ -381,7 +381,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('bold' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_bold = $pValue; } @@ -412,7 +412,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('italic' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_italic = $pValue; } @@ -443,7 +443,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('superScript' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_superScript = $pValue; $this->_subScript = !$pValue; @@ -475,7 +475,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('subScript' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_subScript = $pValue; $this->_superScript = !$pValue; @@ -507,7 +507,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('underline' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_underline = $pValue; } @@ -559,7 +559,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('strike' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_strikethrough = $pValue; } @@ -588,7 +588,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_color = $color; } @@ -618,37 +618,6 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php b/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php index a9df568ec..83a8fc967 100644 --- a/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php +++ b/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable { @@ -203,9 +203,9 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -214,9 +214,9 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -248,7 +248,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('code', $pStyles)) { $this->setFormatCode($pStyles['code']); @@ -288,7 +288,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('code' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_formatCode = $pValue; $this->_builtInFormatCode = self::builtInFormatCodeIndex($pValue); @@ -318,7 +318,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('code' => self::builtInFormatCode($pValue))); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_builtInFormatCode = $pValue; $this->_formatCode = self::builtInFormatCode($pValue); @@ -446,37 +446,6 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ @@ -491,15 +460,59 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable } } + private static $_dateFormatReplacements = array( + // first remove escapes related to non-format characters + '\\' => '', + // 12-hour suffix + 'am/pm' => 'A', + // 4-digit year + 'yyyy' => 'Y', + // 2-digit year + 'yy' => 'y', + // first letter of month - no php equivalent + 'mmmmm' => 'M', + // full month name + 'mmmm' => 'F', + // short month name + 'mmm' => 'M', + // mm is minutes if time or month w/leading zero + ':mm' => ':i', + // month leading zero + 'mm' => 'm', + // month no leading zero + 'm' => 'n', + // full day of week name + 'dddd' => 'l', + // short day of week name + 'ddd' => 'D', + // days leading zero + 'dd' => 'd', + // days no leading zero + 'd' => 'j', + // seconds + 'ss' => 's', + // fractional seconds - no php equivalent + '.s' => '' + ); + private static $_dateFormatReplacements24 = array( + 'hh' => 'H', + 'h' => 'G' + ); + private static $_dateFormatReplacements12 = array( + 'hh' => 'h', + 'h' => 'g' + ); + /** * Convert a value in a pre-defined format to a PHP string * * @param mixed $value Value to format * @param string $format Format code + * @param array $callBack Callback function for additional formatting of string * @return string Formatted string */ - public static function toFormattedString($value = '', $format = '') { - // For now we do not treat strings although part 4 of a format code affects strings + public static function toFormattedString($value = '', $format = '', $callBack = null) { + // For now we do not treat strings although section 4 of a format code affects strings if (!is_numeric($value)) return $value; // For 'General' format code, we just pass the value although this is not entirely the way Excel does it, @@ -508,82 +521,94 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable return $value; } - // Get the parts, there can be up to four parts - $parts = explode(';', $format); + // Get the sections, there can be up to four sections + $sections = explode(';', $format); - // We should really fetch the relevant part depending on whether we have a positive number, - // negative number, zero, or text. But for now we just use first part - $format = $parts[0]; + // Fetch the relevant section depending on whether number is positive, negative, or zero? + // Text not supported yet. + // Here is how the sections apply to various values in Excel: + // 1 section: [POSITIVE/NEGATIVE/ZERO/TEXT] + // 2 sections: [POSITIVE/ZERO/TEXT] [NEGATIVE] + // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO] + // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT] + switch (count($sections)) { + case 1: + $format = $sections[0]; + break; - if (preg_match("/^[hmsdy]/i", $format)) { // custom datetime format + case 2: + $format = ($value >= 0) ? $sections[0] : $sections[1]; + $value = abs($value); // Use the absolute value + break; + + case 3: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + case 4: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + default: + // something is wrong, just use first section + $format = $sections[0]; + break; + } + + // Save format with color information for later use below + $formatColor = $format; + + // Strip color information + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + $format = preg_replace($color_regex, '', $format); + + // Let's begin inspecting the format and converting the value to a formatted string + if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $format)) { // datetime format // dvc: convert Excel formats to PHP date formats - // first remove escapes related to non-format characters + + // strip off first part containing e.g. [$-F800] or [$USD-409] + // general syntax: [$-] + // language info is in hexadecimal + $format = preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format); // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case $format = strtolower($format); - $format = str_replace('\\', '', $format); - - // 4-digit year - $format = str_replace('yyyy', 'Y', $format); - // 2-digit year - $format = str_replace('yy', 'y', $format); - // first letter of month - no php equivalent - $format = str_replace('mmmmm', 'M', $format); - // full month name - $format = str_replace('mmmm', 'F', $format); - // short month name - $format = str_replace('mmm', 'M', $format); - // mm is minutes if time or month w/leading zero - $format = str_replace(':mm', ':i', $format); - // tmp place holder - $format = str_replace('mm', 'x', $format); - // month no leading zero - $format = str_replace('m', 'n', $format); - // month leading zero - $format = str_replace('x', 'm', $format); - // 12-hour suffix - $format = str_replace('am/pm', 'A', $format); - // full day of week name - $format = str_replace('dddd', 'l', $format); - // short day of week name - $format = str_replace('ddd', 'D', $format); - // tmp place holder - $format = str_replace('dd', 'x', $format); - // days no leading zero - $format = str_replace('d', 'j', $format); - // days leading zero - $format = str_replace('x', 'd', $format); - // seconds - $format = str_replace('ss', 's', $format); - // fractional seconds - no php equivalent - $format = str_replace('.s', '', $format); - - if (!strpos($format,'A')) { // 24-hour format - $format = str_replace('h', 'H', $format); + $format = strtr($format,self::$_dateFormatReplacements); + if (!strpos($format,'A')) { // 24-hour time format + $format = strtr($format,self::$_dateFormatReplacements24); + } else { // 12-hour time format + $format = strtr($format,self::$_dateFormatReplacements12); } - return gmdate($format, PHPExcel_Shared_Date::ExcelToPHP($value)); + $value = gmdate($format, PHPExcel_Shared_Date::ExcelToPHP($value)); } else if (preg_match('/%$/', $format)) { // % number format if ($format === self::FORMAT_PERCENTAGE) { - return round( (100 * $value), 0) . '%'; - } - if (preg_match('/\.[#0]+/i', $format, $m)) { - $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); - $format = str_replace($m[0], $s, $format); - } - if (preg_match('/^[#0]+/', $format, $m)) { - $format = str_replace($m[0], strlen($m[0]), $format); - } - $format = '%' . str_replace('%', 'f%%', $format); + $value = round( (100 * $value), 0) . '%'; + } else { + if (preg_match('/\.[#0]+/i', $format, $m)) { + $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); + $format = str_replace($m[0], $s, $format); + } + if (preg_match('/^[#0]+/', $format, $m)) { + $format = str_replace($m[0], strlen($m[0]), $format); + } + $format = '%' . str_replace('%', 'f%%', $format); - return sprintf($format, 100 * $value); + $value = sprintf($format, 100 * $value); + } } else { if (preg_match ("/^([0-9.,-]+)$/", $value)) { if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { - return 'EUR ' . sprintf('%1.2f', $value); + $value = 'EUR ' . sprintf('%1.2f', $value); } else { // In Excel formats, "_" is used to add spacing, which we can't do in HTML @@ -618,7 +643,8 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $adjustedDecimalPart = $decimalPart/$GCD; $adjustedDecimalDivisor = $decimalDivisor/$GCD; - if (strpos($format,'0') !== false) { + if ((strpos($format,'0') !== false) || (substr($format,0,3) == '? ?')) { + if ($integerPart == 0) { $integerPart = ''; } $value = "$sign$integerPart $adjustedDecimalPart/$adjustedDecimalDivisor"; } else { $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; @@ -633,12 +659,13 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $dec = $matches[2]; $right = $matches[3]; if ($useThousands) { - $localeconv = localeconv(); - if (($localeconv['thousands_sep'] == '') || ($localeconv['decimal_point'] == '')) { - $value = number_format($value, strlen($right), $localeconv['mon_decimal_point'], $localeconv['mon_thousands_sep']); - } else { - $value = number_format($value, strlen($right), $localeconv['decimal_point'], $localeconv['thousands_sep']); - } + $value = number_format( + $value + , strlen($right) + , PHPExcel_Shared_String::getDecimalSeparator() + , PHPExcel_Shared_String::getThousandsSeparator() + ); + } else { $sprintf_pattern = "%1." . strlen($right) . "f"; $value = sprintf($sprintf_pattern, $value); @@ -646,13 +673,16 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $value = preg_replace($number_regex, $value, $format); } } - - return $value; - } } - - return $value; } + + // Additional formatting provided by callback function + if ($callBack !== null) { + list($writerInstance, $function) = $callBack; + $value = $writerInstance->$function($value, $formatColor); + } + + return $value; } } diff --git a/libraries/PHPExcel/PHPExcel/Style/Protection.php b/libraries/PHPExcel/PHPExcel/Style/Protection.php index 57e974d33..12611d13b 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Protection.php +++ b/libraries/PHPExcel/PHPExcel/Style/Protection.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version 1.4.5, 2007-08-23 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Protection implements PHPExcel_IComparable { @@ -149,9 +149,9 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -160,9 +160,9 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -190,7 +190,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('locked', $pStyles)) { $this->setLocked($pStyles['locked']); @@ -226,7 +226,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable public function setLocked($pValue = self::PROTECTION_INHERIT) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('locked' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_locked = $pValue; } @@ -254,7 +254,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable public function setHidden($pValue = self::PROTECTION_INHERIT) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('hidden' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_hidden = $pValue; } @@ -277,37 +277,6 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet.php b/libraries/PHPExcel/PHPExcel/Worksheet.php index c54ab702f..74bd65266 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -88,6 +88,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; /** PHPExcel_Style_Fill */ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Fill.php'; +/** PHPExcel_Style_Color */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; + /** PHPExcel_Style_NumberFormat */ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; @@ -112,7 +115,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet implements PHPExcel_IComparable { @@ -120,6 +123,11 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable const BREAK_NONE = 0; const BREAK_ROW = 1; const BREAK_COLUMN = 2; + + /* Sheet state */ + const SHEETSTATE_VISIBLE = 'visible'; + const SHEETSTATE_HIDDEN = 'hidden'; + const SHEETSTATE_VERYHIDDEN = 'veryHidden'; /** * Parent spreadsheet @@ -176,6 +184,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @var string */ private $_title; + + /** + * Sheet state + * + * @var string + */ + private $_sheetState; /** * Page setup @@ -304,43 +319,36 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable private $_comments = array(); /** - * Selected cell + * Active cell. (Only one!) * * @var string */ - private $_selectedCell = 'A1'; + private $_activeCell = 'A1'; /** - * Temporary property used by style supervisor. Will be removed + * Selected cells * * @var string */ - private $_xActiveCell = 'A1'; - - /** - * Temporary property used by style supervisor. Will be removed - * - * @var string - */ - private $_xSelectedCells = 'A1:A1'; + private $_selectedCells = 'A1'; /** * Cached highest column * * @var string */ - private $_cachedHighestColumn = null; + private $_cachedHighestColumn = 'A'; /** * Cached highest row * * @var int */ - private $_cachedHighestRow = null; + private $_cachedHighestRow = 1; /** * Right-to-left? - * + * * @var boolean */ private $_rightToLeft = false; @@ -359,6 +367,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ private $_dataValidationCollection = array(); + /** + * Tab color + * + * @var PHPExcel_Style_Color + */ + private $_tabColor; + /** * Create a new worksheet * @@ -370,6 +385,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Set parent and title $this->_parent = $pParent; $this->setTitle($pTitle); + $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); // Set page setup $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); @@ -404,6 +420,28 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(null); } + /** + * Check sheet title for valid Excel syntax + * + * @param string $pValue The string to check + * @return string The valid string + * @throws Exception + */ + private static function _checkSheetTitle($pValue) + { + // Some of the printable ASCII characters are invalid: * : / \ ? [ ] + if (preg_match('/(\\*|\\:|\\/|\\\\|\\?|\\[|\\])/', $pValue)) { + throw new Exception('Invalid character found in sheet title'); + } + + // Maximum 31 characters allowed for sheet title + if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { + throw new Exception('Maximum 31 characters allowed in sheet title.'); + } + + return $pValue; + } + /** * Get collection of cells * @@ -555,45 +593,56 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); } - /** - * Calculate widths for auto-size columns - * - * @param boolean $calculateMergeCells Calculate merge cell width - * @return PHPExcel_Worksheet; - */ - public function calculateColumnWidths($calculateMergeCells = false) - { + /** + * Calculate widths for auto-size columns + * + * @param boolean $calculateMergeCells Calculate merge cell width + * @return PHPExcel_Worksheet; + */ + public function calculateColumnWidths($calculateMergeCells = false) + { + // initialize $autoSizes array $autoSizes = array(); - foreach ($this->getColumnDimensions() as $colDimension) { + foreach ($this->getColumnDimensions() as $colDimension) { if ($colDimension->getAutoSize()) { $autoSizes[$colDimension->getColumnIndex()] = -1; } - } - - foreach ($this->getCellCollection() as $cell) { - if (isset($autoSizes[$cell->getColumn()])) { - $cellValue = $cell->getCalculatedValue(); - - foreach ($this->getMergeCells() as $cells) { - if ($cell->isInRange($cells) && !$calculateMergeCells) { - $cellValue = ''; // do not calculate merge cells - } - } - - $autoSizes[$cell->getColumn()] = max( - (float)$autoSizes[$cell->getColumn()], - (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSize(), - false, - $cellValue, - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation() - ) - ); - } } - foreach ($autoSizes as $columnIndex => $width) { - if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); - $this->getColumnDimension($columnIndex)->setWidth($width); + + // There is only something to do if there are some auto-size columns + if (count($autoSizes) > 0) { + // loop though all cells in sheet expand $autoSizes + foreach ($this->getCellCollection(false) as $cell) { + if (isset($autoSizes[$cell->getColumn()])) { + // Calculated value + $cellValue = $cell->getCalculatedValue(); + + // To formatted string + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()); + + foreach ($this->getMergeCells() as $cells) { + if ($cell->isInRange($cells) && !$calculateMergeCells) { + $cellValue = ''; // do not calculate merge cells + } + } + + $autoSizes[$cell->getColumn()] = max( + (float)$autoSizes[$cell->getColumn()], + (float)PHPExcel_Shared_Font::calculateColumnWidth( + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $cellValue, + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getDefaultStyle()->getFont() + ) + ); + } + } + + // adjust column widths + foreach ($autoSizes as $columnIndex => $width) { + if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); + $this->getColumnDimension($columnIndex)->setWidth($width); + } } return $this; @@ -642,7 +691,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * Set title * * @param string $pValue String containing the dimension of this worksheet - * @throws Exception * @return PHPExcel_Worksheet */ public function setTitle($pValue = 'Worksheet') @@ -652,10 +700,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return; } - // Maximum 31 characters allowed for sheet title - if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { - throw new Exception('Maximum 31 characters allowed in sheet title.'); - } + // Syntax check + self::_checkSheetTitle($pValue); // Old title $oldTitle = $this->getTitle(); @@ -684,7 +730,27 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this; } - + + /** + * Get sheet state + * + * @return string Sheet state (visible, hidden, veryHidden) + */ + public function getSheetState() { + return $this->_sheetState; + } + + /** + * Set sheet state + * + * @param string $value Sheet state (visible, hidden, veryHidden) + * @return PHPExcel_Worksheet + */ + public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { + $this->_sheetState = $value; + return $this; + } + /** * Get page setup * @@ -802,36 +868,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function getHighestColumn() { - // Cached? - if (!is_null($this->_cachedHighestColumn)) { - return $this->_cachedHighestColumn; - } - - // Highest column - $highestColumn = -1; - - // Loop trough cells - foreach ($this->_cellCollection as $cell) { - if ($highestColumn < PHPExcel_Cell::columnIndexFromString($cell->getColumn())) { - $highestColumn = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); - } - } - - // Loop trough column dimensions - foreach ($this->_columnDimensions as $dimension) { - if ($highestColumn < PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())) { - $highestColumn = PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex()); - } - } - - // Return & cache - if ($highestColumn < 0) { - $this->_cachedHighestColumn = 'A'; - } else { - $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); - } - - return $this->_cachedHighestColumn; + return $this->_cachedHighestColumn; } /** @@ -841,33 +878,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function getHighestRow() { - // Cached? - if (!is_null($this->_cachedHighestRow)) { - return $this->_cachedHighestRow; - } - - // Highest row - $highestRow = 1; - - // Loop trough cells - foreach ($this->_cellCollection as $cell) { - if ($cell->getRow() > $highestRow) { - $highestRow = $cell->getRow(); - } - } - - // Loop trough row dimensions - foreach ($this->_rowDimensions as $dimension) { - if ($highestRow < $dimension->getRowIndex()) { - $highestRow = $dimension->getRowIndex(); - } - } - - // Cache - $this->_cachedHighestRow = $highestRow; - - // Return - return $highestRow; + return $this->_cachedHighestRow; } /** @@ -949,7 +960,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Named range? if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && - (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches))) { + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); if (!is_null($namedRange)) { $pCoordinate = $namedRange->getRange(); @@ -959,6 +970,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } else { throw new Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); } + } else { + //Allow named ranges within the same sheet. + return $this->getCell($pCoordinate); } } } @@ -971,14 +985,36 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } elseif (strpos($pCoordinate,'$') !== false) { throw new Exception('Cell coordinate must not be absolute.'); } else { + // Create new cell object + // Coordinates $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); $this->_cellCollection[$pCoordinate] = new PHPExcel_Cell($aCoordinates[0], $aCoordinates[1], null, PHPExcel_Cell_DataType::TYPE_NULL, $this); $this->_cellCollectionIsSorted = false; - $this->_cachedHighestColumn = null; - $this->_cachedHighestRow = null; + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) + $this->_cachedHighestColumn = $aCoordinates[0]; + + if ($this->_cachedHighestRow < $aCoordinates[1]) + $this->_cachedHighestRow = $aCoordinates[1]; + + // Cell needs appropriate xfIndex + $rowDimensions = $this->getRowDimensions(); + $columnDimensions = $this->getColumnDimensions(); + + if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { + // then there is a row dimension with explicit style, assign it to the cell + $this->_cellCollection[$pCoordinate]->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); + + } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { + // then there is a column dimension, assign it to the cell + $this->_cellCollection[$pCoordinate]->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); + + } else { + // set to default index + $this->_cellCollection[$pCoordinate]->setXfIndex(0); + } return $this->_cellCollection[$pCoordinate]; } @@ -1001,8 +1037,11 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_cellCollection[$coordinate] = new PHPExcel_Cell($columnLetter, $pRow, null, PHPExcel_Cell_DataType::TYPE_NULL, $this); $this->_cellCollectionIsSorted = false; - $this->_cachedHighestColumn = null; - $this->_cachedHighestRow = null; + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) + $this->_cachedHighestColumn = $pColumn; + + if ($this->_cachedHighestRow < $pRow) + $this->_cachedHighestRow = $pRow; } return $this->_cellCollection[$coordinate]; @@ -1025,7 +1064,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Named range? if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && - (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches))) { + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); if (!is_null($namedRange)) { $pCoordinate = $namedRange->getRange(); @@ -1081,7 +1120,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Get row dimension if (!isset($this->_rowDimensions[$pRow])) { $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); - $this->_cachedHighestRow = null; + + if ($this->_cachedHighestRow < $pRow) + $this->_cachedHighestRow = $pRow; } return $this->_rowDimensions[$pRow]; } @@ -1100,7 +1141,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Fetch dimensions if (!isset($this->_columnDimensions[$pColumn])) { $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); - $this->_cachedHighestColumn = null; + + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) + $this->_cachedHighestColumn = $pColumn; } return $this->_columnDimensions[$pColumn]; } @@ -1147,9 +1190,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @throws Exception * @return PHPExcel_Worksheet */ - public function setDefaultStyle(PHPExcel_Style $value) + public function setDefaultStyle(PHPExcel_Style $pValue) { - $this->_parent->setDefaultStyle($value); + $this->_parent->getDefaultStyle()->applyFromArray(array( + 'font' => array( + 'name' => $pValue->getFont()->getName(), + 'size' => $pValue->getFont()->getSize(), + ), + )); return $this; } @@ -1166,7 +1214,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); // set cell coordinate as active - $this->setXSelectedCells($pCellCoordinate); + $this->setSelectedCells($pCellCoordinate); return $this->_parent->getCellXfSupervisor(); } @@ -1317,7 +1365,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $rangeEnd = $tmp; } - // Loop trough cells and apply styles + // Loop through cells and apply styles for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col) . $row)->setXfIndex($xfIndex); @@ -1472,7 +1520,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } /** - * Get merge cells + * Get merge cells array. * * @return array[] */ @@ -1481,6 +1529,19 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this->_mergeCells; } + /** + * Set merge cells array for the entire sheet. Use instead mergeCells() to merge + * a single cell range. + * + * @param array + */ + public function setMergeCells($pValue = array()) + { + $this->_mergeCells = $pValue; + + return $this; + } + /** * Set protection on a cell range * @@ -1912,72 +1973,76 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable /** * Get selected cell * + * @deprecated * @return string */ public function getSelectedCell() { - return $this->_selectedCell; + return $this->getSelectedCells(); } /** - * Temporary method used by style supervisor. Will be removed + * Get active cell * - * @return string + * @return string Example: 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->_xActiveCell; + return $this->_activeCell; } /** - * Temporary method used by style supervisor. Will be removed + * Get selected cells * * @return string */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->_xSelectedCells; + return $this->_selectedCells; } /** * Selected cell * * @param string $pCell Cell (i.e. A1) - * @throws Exception * @return PHPExcel_Worksheet */ - public function setSelectedCell($pCell = '') + public function setSelectedCell($pCoordinate = 'A1') { - // Uppercase coordinate - $pCell = strtoupper($pCell); - - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - $this->_selectedCell = $pCell; - } else { - throw new Exception('Selected cell can not be set on a range of cells.'); - } - return $this; + return $this->setSelectedCells($pCoordinate); } /** - * Temporary method used by style supervisor. Will be removed + * Select a range of cells. * - * @param string $pCell Cell (i.e. A1) + * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' * @throws Exception * @return PHPExcel_Worksheet */ - public function setXSelectedCells($pCoordinate = 'A1:A1') + public function setSelectedCells($pCoordinate = 'A1') { - // Uppercase coordinate + // Uppercase coordinate $pCoordinate = strtoupper($pCoordinate); + // Convert 'A' to 'A:A' + $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); + + // Convert '1' to '1:1' + $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); + + // Convert 'A:C' to 'A1:C1048576' + $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); + + // Convert '1:3' to 'A1:XFD3' + $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); - $this->_xActiveCell = $first[0]; + $this->_activeCell = $first[0]; } else { - $this->_xActiveCell = $pCoordinate; + $this->_activeCell = $pCoordinate; } - $this->_xSelectedCells = $pCoordinate; + $this->_selectedCells = $pCoordinate; return $this; } @@ -1991,24 +2056,24 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 0) { - return $this->setSelectedCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); } /** * Get right-to-left - * + * * @return boolean */ public function getRightToLeft() { return $this->_rightToLeft; } - + /** * Set right-to-left - * + * * @param boolean $value Right-to-left true/false * @return PHPExcel_Worksheet - */ + */ public function setRightToLeft($value = false) { $this->_rightToLeft = $value; return $this; @@ -2028,7 +2093,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($pCell); $startColumn = PHPExcel_Cell::columnIndexFromString($startColumn) - 1; - // Loop trough $source + // Loop through $source $currentRow = $startRow - 1; $rowData = null; foreach ($source as $rowData) { @@ -2071,7 +2136,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; - // Loop trough cells + // Loop through cells for ($row = $dimension[0][1]; $row <= $dimension[1][1]; ++$row) { for ($column = $dimension[0][0]; $column <= $dimension[1][0]; ++$column) { // Cell exists? @@ -2125,6 +2190,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $iterator->next(); } + // Lookup highest column and highest row if cells are cleaned + $highestColumn = -1; + $highestRow = 1; + // Find cells that can be cleaned foreach ($this->_cellCollection as $coordinate => $cell) { // Can be cleaned? @@ -2145,10 +2214,42 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Clean? if ($canBeCleaned) { + // Remove the cell unset($this->_cellCollection[$coordinate]); - } + } else { + // Determine highest column and row + if ($highestColumn < PHPExcel_Cell::columnIndexFromString($cell->getColumn())) { + $highestColumn = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); + } + if ($cell->getRow() > $highestRow) { + $highestRow = $cell->getRow(); + } + } } + // Loop through column dimensions + foreach ($this->_columnDimensions as $dimension) { + if ($highestColumn < PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())) { + $highestColumn = PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex()); + } + } + + // Loop through row dimensions + foreach ($this->_rowDimensions as $dimension) { + if ($highestRow < $dimension->getRowIndex()) { + $highestRow = $dimension->getRowIndex(); + } + } + + // Cache values + if ($highestColumn < 0) { + $this->_cachedHighestColumn = 'A'; + } else { + $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); + } + $this->_cachedHighestRow = $highestRow; + + // Return return $this; } @@ -2167,37 +2268,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Extract worksheet title from range. * @@ -2350,6 +2420,42 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this->_dataValidationCollection; } + /** + * Get tab color + * + * @return PHPExcel_Style_Color + */ + public function getTabColor() + { + if (is_null($this->_tabColor)) + $this->_tabColor = new PHPExcel_Style_Color(); + + return $this->_tabColor; + } + + /** + * Reset tab color + * + * @return PHPExcel_Worksheet + */ + public function resetTabColor() + { + $this->_tabColor = null; + unset($this->_tabColor); + + return $this; + } + + /** + * Tab color set? + * + * @return boolean + */ + public function isTabColorSet() + { + return !is_null($this->_tabColor); + } + /** * Copy worksheet (!= clone!) * diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php index 364689863..79f8c1611 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -48,7 +48,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -486,37 +486,6 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php b/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php index 6581cab62..f0683e6e4 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -51,7 +51,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_CellIterator extends IteratorIterator { @@ -115,20 +115,7 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator * @return PHPExcel_Cell */ public function current() { - $cellExists = $this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex); - if ( ($this->_onlyExistingCells && $cellExists) || (!$this->_onlyExistingCells) ) { - return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); - } else if ($this->_onlyExistingCells && !$cellExists) { - // Loop untill we find one - while ($this->valid()) { - $this->next(); - if ($this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex)) { - return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); - } - } - } - - return null; + return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); } /** @@ -153,7 +140,23 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator * @return boolean */ public function valid() { - return $this->_position < PHPExcel_Cell::columnIndexFromString( $this->_subject->getHighestColumn() ); + // columnIndexFromString() returns an index based at one, + // treat it as a count when comparing it to the base zero + // position. + $columnCount = PHPExcel_Cell::columnIndexFromString($this->_subject->getHighestColumn()); + + if ($this->_onlyExistingCells) { + // If we aren't looking at an existing cell, either + // because the first column doesn't exist or next() has + // been called onto a nonexistent cell, then loop until we + // find one, or pass the last column. + while ($this->_position < $columnCount && + !$this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex)) { + ++$this->_position; + } + } + + return $this->_position < $columnCount; } /** diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php b/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php index ada5bf166..7b6810fbf 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_ColumnDimension { @@ -78,9 +78,16 @@ class PHPExcel_Worksheet_ColumnDimension * @var bool */ private $_collapsed; - + + /** + * Index to cellXf + * + * @var int + */ + private $_xfIndex; + /** - * Create a new PHPExcel_Worksheet_RowDimension + * Create a new PHPExcel_Worksheet_ColumnDimension * * @param string $pIndex Character column index */ @@ -93,6 +100,9 @@ class PHPExcel_Worksheet_ColumnDimension $this->_visible = true; $this->_outlineLevel = 0; $this->_collapsed = false; + + // set default index to cellXf + $this->_xfIndex = 0; } /** @@ -222,6 +232,28 @@ class PHPExcel_Worksheet_ColumnDimension return $this; } + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + return $this; + } + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ @@ -235,4 +267,5 @@ class PHPExcel_Worksheet_ColumnDimension } } } + } diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php index 780662e9e..e6f84e226 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -153,37 +153,6 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php index c931671fd..a294e5a0e 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -48,7 +48,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable { @@ -289,37 +289,6 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php index b985bf8b3..ef60e77a9 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -103,7 +103,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooter { @@ -457,7 +457,7 @@ class PHPExcel_Worksheet_HeaderFooter /** * Get header/footer images * - * @return HPExcel_Worksheet_HeaderFooterDrawing[] + * @return PHPExcel_Worksheet_HeaderFooterDrawing[] */ public function getImages() { // Sort array diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php index 3589cde4e..d3be4b75a 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable { @@ -354,37 +354,6 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php index 5d80d7a57..05a45dfee 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -205,37 +205,6 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php b/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php index aad7d2091..80ee4cfe0 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_PageMargins { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php b/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php index d7584a32e..1424fe062 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -102,7 +102,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_PageSetup { @@ -203,6 +203,14 @@ class PHPExcel_Worksheet_PageSetup */ private $_scale; + /** + * Fit To Page + * Whether scale or fitToWith / fitToHeight applies + * + * @var boolean + */ + private $_fitToPage; + /** * Fit To Height * Number of vertical pages to fit on @@ -253,6 +261,13 @@ class PHPExcel_Worksheet_PageSetup * @var string */ private $_printArea = null; + + /** + * First page number + * + * @var int + */ + private $_firstPageNumber = null; /** * Create a new PHPExcel_Worksheet_PageSetup @@ -262,14 +277,16 @@ class PHPExcel_Worksheet_PageSetup // Initialise values $this->_paperSize = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER; $this->_orientation = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT; - $this->_scale = null; - $this->_fitToHeight = null; - $this->_fitToWidth = null; + $this->_scale = 100; + $this->_fitToPage = false; + $this->_fitToHeight = 1; + $this->_fitToWidth = 1; $this->_columnsToRepeatAtLeft = array('', ''); $this->_rowsToRepeatAtTop = array(0, 0); $this->_horizontalCentered = false; $this->_verticalCentered = false; $this->_printArea = null; + $this->_firstPageNumber = null; } /** @@ -328,20 +345,44 @@ class PHPExcel_Worksheet_PageSetup * This setting is overridden when fitToWidth and/or fitToHeight are in use * * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth * @throws Exception * @return PHPExcel_Worksheet_PageSetup */ - public function setScale($pValue = 100) { + public function setScale($pValue = 100, $pUpdate = true) { // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, // but it is apparently still able to handle any scale >= 0, where 0 results in 100 if (($pValue >= 0) || is_null($pValue)) { $this->_scale = $pValue; + if ($pUpdate) { + $this->_fitToPage = false; + } } else { throw new Exception("Scale must not be negative"); } return $this; } + /** + * Get Fit To Page + * + * @return boolean + */ + public function getFitToPage() { + return $this->_fitToPage; + } + + /** + * Set Fit To Page + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToPage($pValue = true) { + $this->_fitToPage = $pValue; + return $this; + } + /** * Get Fit To Height * @@ -355,11 +396,13 @@ class PHPExcel_Worksheet_PageSetup * Set Fit To Height * * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling * @return PHPExcel_Worksheet_PageSetup */ - public function setFitToHeight($pValue = 1) { - if ($pValue != '') { - $this->_fitToHeight = $pValue; + public function setFitToHeight($pValue = 1, $pUpdate = true) { + $this->_fitToHeight = $pValue; + if ($pUpdate) { + $this->_fitToPage = true; } return $this; } @@ -377,11 +420,13 @@ class PHPExcel_Worksheet_PageSetup * Set Fit To Width * * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling * @return PHPExcel_Worksheet_PageSetup */ - public function setFitToWidth($pValue = 1) { - if ($pValue != '') { - $this->_fitToWidth = $pValue; + public function setFitToWidth($pValue = 1, $pUpdate = true) { + $this->_fitToWidth = $pValue; + if ($pUpdate) { + $this->_fitToPage = true; } return $this; } @@ -543,7 +588,7 @@ class PHPExcel_Worksheet_PageSetup } /** - * Set print area + * Set print area. E.g. 'A1:D10' or 'A1:D10,G5:M20' * * @param string $value * @throws Exception @@ -573,6 +618,35 @@ class PHPExcel_Worksheet_PageSetup { return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2); } + + /** + * Get first page number + * + * @return int + */ + public function getFirstPageNumber() { + return $this->_firstPageNumber; + } + + /** + * Set first page number + * + * @param int $value + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstPageNumber($value = null) { + $this->_firstPageNumber = $value; + return $this; + } + + /** + * Reset first page number + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function resetFirstPageNumber() { + return $this->setFirstPageNumber(null); + } /** * Implement PHP __clone to create a deep clone, not just a shallow copy. diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php b/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php index 1116c56da..d87c208e0 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Protection { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Row.php b/libraries/PHPExcel/PHPExcel/Worksheet/Row.php index 1aa46cd08..d2105cb10 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Row.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Row.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -51,7 +51,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/CellIterator.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Row { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php b/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php index 76cc13249..e956c2424 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_RowDimension { @@ -71,7 +71,14 @@ class PHPExcel_Worksheet_RowDimension * @var bool */ private $_collapsed; - + + /** + * Index to cellXf. Null value means row has no explicit cellXf format. + * + * @var int|null + */ + private $_xfIndex; + /** * Create a new PHPExcel_Worksheet_RowDimension * @@ -85,6 +92,9 @@ class PHPExcel_Worksheet_RowDimension $this->_visible = true; $this->_outlineLevel = 0; $this->_collapsed = false; + + // set row dimension as unformatted by default + $this->_xfIndex = null; } /** @@ -193,7 +203,29 @@ class PHPExcel_Worksheet_RowDimension $this->_collapsed = $pValue; return $this; } - + + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + return $this; + } + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php b/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php index 459b6d07b..58b0dcaf4 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -51,7 +51,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Row.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_RowIterator extends IteratorIterator { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php b/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php index 642595f64..684ef8a21 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_SheetView { diff --git a/libraries/PHPExcel/PHPExcel/WorksheetIterator.php b/libraries/PHPExcel/PHPExcel/WorksheetIterator.php index 9edcc311f..57f0d5c45 100644 --- a/libraries/PHPExcel/PHPExcel/WorksheetIterator.php +++ b/libraries/PHPExcel/PHPExcel/WorksheetIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -48,7 +48,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_WorksheetIterator extends IteratorIterator { diff --git a/libraries/PHPExcel/PHPExcel/Writer/CSV.php b/libraries/PHPExcel/PHPExcel/Writer/CSV.php index 76b64f251..fd29f1559 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/CSV.php +++ b/libraries/PHPExcel/PHPExcel/Writer/CSV.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { /** diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php index 151fc1e47..81b00922a 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -94,7 +94,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Comments.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php index e7ef3d667..7b559f569 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -67,7 +67,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_WriterPart { @@ -107,14 +107,14 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $objWriter->startElement('comments'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - // Loop trough authors + // Loop through authors $objWriter->startElement('authors'); foreach ($authors as $author => $index) { $objWriter->writeElement('author', $author); } $objWriter->endElement(); - // Loop trough comments + // Loop through comments $objWriter->startElement('commentList'); foreach ($comments as $key => $value) { $this->_writeComment($objWriter, $key, $value, $authors); @@ -212,7 +212,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $objWriter->endElement(); - // Loop trough comments + // Loop through comments foreach ($comments as $key => $value) { $this->_writeVMLComment($objWriter, $key, $value); } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php index ebe7d0f47..17505f5e0 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php index fcd845906..3046cb5ce 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php index f7d9f9895..584c65d89 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -70,7 +70,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_WriterPart { @@ -99,7 +99,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); - // Loop trough images and write drawings + // Loop through images and write drawings $i = 1; $iterator = $pWorksheet->getDrawingCollection()->getIterator(); while ($iterator->valid()) { @@ -469,7 +469,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer $objWriter->endElement(); - // Loop trough images + // Loop through images foreach ($images as $key => $value) { $this->_writeVMLHeaderFooterImage($objWriter, $key, $value); } @@ -535,10 +535,10 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer // Get an array of all drawings $aDrawings = array(); - // Loop trough PHPExcel + // Loop through PHPExcel $sheetCount = $pPHPExcel->getSheetCount(); for ($i = 0; $i < $sheetCount; ++$i) { - // Loop trough images and add to array + // Loop through images and add to array $iterator = $pPHPExcel->getSheet($i)->getDrawingCollection()->getIterator(); while ($iterator->valid()) { $aDrawings[] = $iterator->current(); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php index fd8ad849e..ba81c1be5 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPart { @@ -219,13 +219,13 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar // Write hyperlink relationships? $i = 1; - foreach ($pWorksheet->getCellCollection() as $cell) { - if ($cell->hasHyperlink() && !$cell->getHyperlink()->isInternal()) { + foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) { + if (!$hyperlink->isInternal()) { $this->_writeRelationship( $objWriter, '_hyperlink_' . $i, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', - $cell->getHyperlink()->getUrl(), + $hyperlink->getUrl(), 'External' ); @@ -292,7 +292,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar $objWriter->startElement('Relationships'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Loop trough images and write relationships + // Loop through images and write relationships $i = 1; $iterator = $pWorksheet->getDrawingCollection()->getIterator(); while ($iterator->valid()) { @@ -341,7 +341,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar $objWriter->startElement('Relationships'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Loop trough images and write relationships + // Loop through images and write relationships foreach ($pWorksheet->getHeaderFooter()->getImages() as $key => $value) { // Write relationship for image drawing $this->_writeRelationship( diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php index f1bc7168f..1e67d932d 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_WriterPart { @@ -83,7 +83,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // Fill index array $aFlippedStringTable = $this->flipStringTable($aStringTable); - // Loop trough cells + // Loop through cells $cellCollection = $pSheet->getCellCollection(); foreach ($cellCollection as $cell) { if (!is_object($cell->getValue()) && @@ -137,7 +137,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); $objWriter->writeAttribute('uniqueCount', count($pStringTable)); - // Loop trough string table + // Loop through string table foreach ($pStringTable as $textElement) { $objWriter->startElement('si'); @@ -174,7 +174,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr */ public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null) { - // Loop trough rich text elements + // Loop through rich text elements $elements = $pRichText->getRichTextElements(); foreach ($elements as $element) { // r @@ -237,7 +237,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // t $objWriter->startElement('t'); $objWriter->writeAttribute('xml:space', 'preserve'); - $objWriter->writeRaw(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( htmlspecialchars($element->getText()) )); + $objWriter->writeRaw(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); $objWriter->endElement(); $objWriter->endElement(); @@ -254,7 +254,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // Return value $returnValue = array(); - // Loop trough stringtable and add flipped items to $returnValue + // Loop through stringtable and add flipped items to $returnValue foreach ($stringTable as $key => $value) { if (! $value instanceof PHPExcel_RichText) { $returnValue[$value] = $key; diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php index eca0ac781..8a41a6f35 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -79,7 +79,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPart { @@ -396,6 +396,10 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->writeAttribute('diagonalUp', 'false'); $objWriter->writeAttribute('diagonalDown', 'true'); break; + case PHPExcel_Style_Borders::DIAGONAL_BOTH: + $objWriter->writeAttribute('diagonalUp', 'true'); + $objWriter->writeAttribute('diagonalDown', 'true'); + break; } // BorderPr diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php index cd8c2c932..cf4565c78 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php index 7bf7f2454..727a5d32f 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_WriterPart { @@ -244,7 +244,8 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write $objWriter, $pPHPExcel->getSheet($i)->getTitle(), ($i + 1), - ($i + 1 + 3) + ($i + 1 + 3), + $pPHPExcel->getSheet($i)->getSheetState() ); } @@ -258,15 +259,19 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param string $pSheetname Sheet name * @param int $pSheetId Sheet id * @param int $pRelId Relationship ID + * @param string $sheetState Sheet state (visible, hidden, veryHidden) * @throws Exception */ - private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1) + private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') { if ($pSheetname != '') { // Write sheet $objWriter->startElement('sheet'); $objWriter->writeAttribute('name', $pSheetname); $objWriter->writeAttribute('sheetId', $pSheetId); + if ($sheetState != 'visible' && $sheetState != '') { + $objWriter->writeAttribute('state', $sheetState); + } $objWriter->writeAttribute('r:id', 'rId' . $pRelId); $objWriter->endElement(); } else { @@ -449,11 +454,15 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write // Print area $printArea = PHPExcel_Cell::splitRange($pSheet->getPageSetup()->getPrintArea()); - $printArea = $printArea[0]; - $printArea[0] = PHPExcel_Cell::absoluteCoordinate($printArea[0]); - $printArea[1] = PHPExcel_Cell::absoluteCoordinate($printArea[1]); - $objWriter->writeRaw('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printArea)); + $chunks = array(); + foreach ($printArea as $printAreaRect) { + $printAreaRect[0] = PHPExcel_Cell::absoluteCoordinate($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::absoluteCoordinate($printAreaRect[1]); + $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect); + } + + $objWriter->writeRaw(implode(',', $chunks)); $objWriter->endElement(); } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php index 45296cbfc..30fdc5f87 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -73,7 +73,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_WriterPart { @@ -190,6 +190,13 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->startElement('sheetPr'); //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); + // tabColor + if ($pSheet->isTabColorSet()) { + $objWriter->startElement('tabColor'); + $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB()); + $objWriter->endElement(); + } + // outlinePr $objWriter->startElement('outlinePr'); $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0')); @@ -197,7 +204,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->endElement(); // pageSetUpPr - if (!is_null($pSheet->getPageSetup()->getFitToHeight()) || !is_null($pSheet->getPageSetup()->getFitToWidth())) { + if ($pSheet->getPageSetup()->getFitToPage()) { $objWriter->startElement('pageSetUpPr'); $objWriter->writeAttribute('fitToPage', '1'); $objWriter->endElement(); @@ -286,8 +293,8 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Selection $objWriter->startElement('selection'); - $objWriter->writeAttribute('activeCell', $pSheet->getSelectedCell()); - $objWriter->writeAttribute('sqref', $pSheet->getSelectedCell()); + $objWriter->writeAttribute('activeCell', $pSheet->getActiveCell()); + $objWriter->writeAttribute('sqref', $pSheet->getSelectedCells()); $objWriter->endElement(); $objWriter->endElement(); @@ -351,66 +358,59 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ private function _writeCols(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { // cols - $objWriter->startElement('cols'); + if (count($pSheet->getColumnDimensions()) > 0) { + $objWriter->startElement('cols'); - // Check if there is at least one column dimension specified. If not, create one. - if (count($pSheet->getColumnDimensions()) == 0) { - if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) { - $pSheet->getColumnDimension('A')->setWidth($pSheet->getDefaultColumnDimension()->getWidth()); - } else { - $pSheet->getColumnDimension('A')->setWidth(9.10); - } - } + $pSheet->calculateColumnWidths(); - $pSheet->calculateColumnWidths(); + // Loop through column dimensions + foreach ($pSheet->getColumnDimensions() as $colDimension) { + // col + $objWriter->startElement('col'); + $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); - // Loop trough column dimensions - foreach ($pSheet->getColumnDimensions() as $colDimension) { - // col - $objWriter->startElement('col'); - $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); - $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + if ($colDimension->getWidth() < 0) { + // No width set, apply default of 10 + $objWriter->writeAttribute('width', '9.10'); + } else { + // Width set + $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); + } - if ($colDimension->getWidth() < 0) { - // No width set, apply default of 10 - $objWriter->writeAttribute('width', '9.10'); - } else { - // Width set - $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); + // Column visibility + if ($colDimension->getVisible() == false) { + $objWriter->writeAttribute('hidden', 'true'); + } + + // Auto size? + if ($colDimension->getAutoSize()) { + $objWriter->writeAttribute('bestFit', 'true'); + } + + // Custom width? + if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { + $objWriter->writeAttribute('customWidth', 'true'); + } + + // Collapsed + if ($colDimension->getCollapsed() == true) { + $objWriter->writeAttribute('collapsed', 'true'); + } + + // Outline level + if ($colDimension->getOutlineLevel() > 0) { + $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); + } + + // Style + $objWriter->writeAttribute('style', $colDimension->getXfIndex()); + + $objWriter->endElement(); } - // Column visibility - if ($colDimension->getVisible() == false) { - $objWriter->writeAttribute('hidden', 'true'); - } - - // Auto size? - if ($colDimension->getAutoSize()) { - $objWriter->writeAttribute('bestFit', 'true'); - } - - // Custom width? - if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { - $objWriter->writeAttribute('customWidth', 'true'); - } - - // Collapsed - if ($colDimension->getCollapsed() == true) { - $objWriter->writeAttribute('collapsed', 'true'); - } - - // Outline level - if ($colDimension->getOutlineLevel() > 0) { - $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); - } - - // Style - $objWriter->writeAttribute('style', 0); - - $objWriter->endElement(); - } - - $objWriter->endElement(); + $objWriter->endElement(); + } } /** @@ -460,7 +460,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Conditional id $id = 1; - // Loop trough styles in the current worksheet + // Loop through styles in the current worksheet foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { foreach ($conditionalStyles as $conditional) { // WHY was this again? @@ -491,7 +491,23 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('text', $conditional->getText()); } - if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_CONTAINSTEXT + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BEGINSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_ENDSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_NOTCONTAINS + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) { foreach ($conditional->getConditions() as $formula) { @@ -517,20 +533,15 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ */ private function _writeDataValidations(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { - // Build a temporary array of datavalidation objects - $aDataValidations = array(); - foreach ($pSheet->getCellCollection() as $cell) { - if ($cell->hasDataValidation()) { - $aDataValidations[] = $cell->getDataValidation(); - } - } + // Datavalidation collection + $dataValidationCollection = $pSheet->getDataValidationCollection(); // Write data validations? - if (count($aDataValidations) > 0) { + if (count($dataValidationCollection) > 0) { $objWriter->startElement('dataValidations'); - $objWriter->writeAttribute('count', count($aDataValidations)); + $objWriter->writeAttribute('count', count($dataValidationCollection)); - foreach ($aDataValidations as $dv) { + foreach ($dataValidationCollection as $coordinate => $dv) { $objWriter->startElement('dataValidation'); if ($dv->getType() != '') { @@ -563,7 +574,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('prompt', $dv->getPrompt()); } - $objWriter->writeAttribute('sqref', $dv->getParent()->getCoordinate()); + $objWriter->writeAttribute('sqref', $coordinate); if ($dv->getFormula1() !== '') { $objWriter->writeElement('formula1', $dv->getFormula1()); @@ -588,25 +599,20 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ */ private function _writeHyperlinks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { - // Build a temporary array of hyperlink objects - $aHyperlinks = array(); - foreach ($pSheet->getCellCollection() as $cell) { - if ($cell->hasHyperlink()) { - $aHyperlinks[] = $cell->getHyperlink(); - } - } + // Hyperlink collection + $hyperlinkCollection = $pSheet->getHyperlinkCollection(); // Relation ID $relationId = 1; // Write hyperlinks? - if (count($aHyperlinks) > 0) { + if (count($hyperlinkCollection) > 0) { $objWriter->startElement('hyperlinks'); - foreach ($aHyperlinks as $hyperlink) { + foreach ($hyperlinkCollection as $coordinate => $hyperlink) { $objWriter->startElement('hyperlink'); - $objWriter->writeAttribute('ref', $hyperlink->getParent()->getCoordinate()); + $objWriter->writeAttribute('ref', $coordinate); if (!$hyperlink->isInternal()) { $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId); ++$relationId; @@ -755,17 +761,21 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation()); if (!is_null($pSheet->getPageSetup()->getScale())) { - $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); + $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); } if (!is_null($pSheet->getPageSetup()->getFitToHeight())) { - $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); + $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); } else { - $objWriter->writeAttribute('fitToHeight', '0'); + $objWriter->writeAttribute('fitToHeight', '0'); } if (!is_null($pSheet->getPageSetup()->getFitToWidth())) { - $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); + $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); } else { - $objWriter->writeAttribute('fitToWidth', '0'); + $objWriter->writeAttribute('fitToWidth', '0'); + } + if (!is_null($pSheet->getPageSetup()->getFirstPageNumber())) { + $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber()); + $objWriter->writeAttribute('useFirstPageNumber', '1'); } $objWriter->endElement(); @@ -876,7 +886,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Highest row number $highestRow = $pSheet->getHighestRow(); - // Loop trough cells + // Loop through cells $cellCollection = $pSheet->getCellCollection(); $cellsByRow = array(); @@ -887,13 +897,14 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ for ($currentRow = 1; $currentRow <= $highestRow; ++$currentRow) { // Get row dimension $rowDimension = $pSheet->getRowDimension($currentRow); - + // Write current row? $writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || - $rowDimension->getOutlineLevel() > 0; + $rowDimension->getOutlineLevel() > 0 || + $rowDimension->getXfIndex() !== null; if ($writeCurrentRow) { // Start a new row @@ -922,6 +933,12 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel()); } + // Style + if ($rowDimension->getXfIndex() !== null) { + $objWriter->writeAttribute('s', $rowDimension->getXfIndex()); + $objWriter->writeAttribute('customFormat', '1'); + } + // Write cells if (isset($cellsByRow[$currentRow])) { foreach($cellsByRow[$currentRow] as $cell) { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php index 473a813da..c09d05a19 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ abstract class PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5.php index abc9c655b..050e066f8 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,6 +43,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; /** PHPExcel_HashTable */ require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; +/** PHPExcel_Shared_File */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; + /** PHPExcel_Shared_OLE_PPS_Root */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_Root.php'; @@ -61,10 +64,17 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Workbook.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter { + /** + * Pre-calculate formulas + * + * @var boolean + */ + private $_preCalculateFormulas; + /** * PHPExcel object * @@ -107,6 +117,13 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter */ private $_str_table; + /** + * Color cache. Mapping between RGB value and color index. + * + * @var array + */ + private $_colors; + /** * Formula parser * @@ -121,9 +138,10 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter * @param PHPExcel $phpExcel PHPExcel object */ public function __construct(PHPExcel $phpExcel) { + $this->_preCalculateFormulas = true; $this->_phpExcel = $phpExcel; $this->_BIFF_version = 0x0600; - $this->_tempDir = ''; + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); $this->_str_total = 0; $this->_str_unique = 0; @@ -151,9 +169,12 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + // initialize colors array + $this->_colors = array(); + // Initialise workbook writer $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, $this->_BIFF_version, - $this->_str_total, $this->_str_unique, $this->_str_table, $this->_parser, $this->_tempDir); + $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser, $this->_tempDir); // Initialise worksheet writers $countSheets = count($this->_phpExcel->getAllSheets()); @@ -162,8 +183,9 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $writerWorksheet = new PHPExcel_Writer_Excel5_Worksheet($this->_BIFF_version, $this->_str_total, $this->_str_unique, - $this->_str_table, + $this->_str_table, $this->_colors, $this->_parser, $this->_tempDir, + $this->_preCalculateFormulas, $phpSheet); $this->_writerWorksheets[$i] = $writerWorksheet; } @@ -248,4 +270,22 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter return $this; } + /** + * Get Pre-Calculate Formulas + * + * @return boolean + */ + public function getPreCalculateFormulas() { + return $this->_preCalculateFormulas; + } + + /** + * Set Pre-Calculate Formulas + * + * @param boolean $pValue Pre-Calculate Formulas? + */ + public function setPreCalculateFormulas($pValue = true) { + $this->_preCalculateFormulas = $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php index befcc88f6..b293ddeeb 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class): @@ -65,7 +65,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_BIFFwriter { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php index b2d8d074b..4d5f22bd1 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Escher { @@ -395,7 +395,7 @@ class PHPExcel_Writer_Excel5_Escher $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0xA000); + $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00); // the options @@ -447,7 +447,7 @@ class PHPExcel_Writer_Excel5_Escher // end offsetY $endOffsetY = $this->_object->getEndOffsetY(); - $clientAnchorData = pack('vvvvvvvvv', 0x00, + $clientAnchorData = pack('vvvvvvvvv', 0x02, $c1, $startOffsetX, $r1, $startOffsetY, $c2, $endOffsetX, $r2, $endOffsetY); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php index 6f5194054..97a553140 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Font { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php index b436a4f0f..116513d45 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Parser (used as the base for this class): @@ -70,7 +70,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/BIFFwriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Parser { @@ -533,12 +533,12 @@ class PHPExcel_Writer_Excel5_Parser } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) { return $this->_convertRef2d($token); - // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 - } elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z](\d+)$/u",$token)) { + // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 + } elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { return $this->_convertRef3d($token); - // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 - } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z](\d+)$/u",$token)) { + // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 + } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { return $this->_convertRef3d($token); // match ranges like A1:B2 @@ -549,12 +549,12 @@ class PHPExcel_Writer_Excel5_Parser } elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token)) { return $this->_convertRange2d($token); - // match external ranges like Sheet1!A1 or Sheet1:Sheet2!A1:B2 - } elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/u",$token)) { + // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + } elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { return $this->_convertRange3d($token); - // match external ranges like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2 - } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/u",$token)) { + // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { return $this->_convertRange3d($token); // operators (including parentheses) @@ -652,9 +652,9 @@ class PHPExcel_Writer_Excel5_Parser // TODO: possible class value 0,1,2 check Formula.pm // Split the range into 2 cell refs if (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\:([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) { - list($cell1, $cell2) = split(':', $range); + list($cell1, $cell2) = explode(':', $range); } elseif (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\.\.([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) { - list($cell1, $cell2) = split('\.\.', $range); + list($cell1, $cell2) = explode('..', $range); } else { // TODO: use real error codes @@ -694,7 +694,7 @@ class PHPExcel_Writer_Excel5_Parser $class = 2; // as far as I know, this is magick. // Split the ref at the ! symbol - list($ext_ref, $range) = split('!', $token); + list($ext_ref, $range) = explode('!', $token); // Convert the external reference part (different for BIFF8) if ($this->_BIFF_version == 0x0500) { @@ -704,10 +704,10 @@ class PHPExcel_Writer_Excel5_Parser } // Split the range into 2 cell refs - list($cell1, $cell2) = split(':', $range); + list($cell1, $cell2) = explode(':', $range); // Convert the cell references - if (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/", $cell1)) { + if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) { $cell_array1 = $this->_cellToPackedRowcol($cell1); list($row1, $col1) = $cell_array1; $cell_array2 = $this->_cellToPackedRowcol($cell2); @@ -773,7 +773,7 @@ class PHPExcel_Writer_Excel5_Parser $class = 2; // as far as I know, this is magick. // Split the ref at the ! symbol - list($ext_ref, $cell) = split('!', $cell); + list($ext_ref, $cell) = explode('!', $cell); // Convert the external reference part (different for BIFF8) if ($this->_BIFF_version == 0x0500) { @@ -814,7 +814,7 @@ class PHPExcel_Writer_Excel5_Parser // Check if there is a sheet range eg., Sheet1:Sheet2. if (preg_match("/:/", $ext_ref)) { - list($sheet_name1, $sheet_name2) = split(':', $ext_ref); + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { @@ -859,7 +859,7 @@ class PHPExcel_Writer_Excel5_Parser // Check if there is a sheet range eg., Sheet1:Sheet2. if (preg_match("/:/", $ext_ref)) { - list($sheet_name1, $sheet_name2) = split(':', $ext_ref); + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { @@ -1158,47 +1158,47 @@ class PHPExcel_Writer_Excel5_Parser default: // if it's a reference if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and - !ereg("[0-9]",$this->_lookahead) and + !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.') and ($this->_lookahead != '!')) { return $token; } - // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) - elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead) and + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.')) { return $token; } // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead) and + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.')) { return $token; } // if it's a range (A1:A2) elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and - !ereg("[0-9]",$this->_lookahead)) + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } // if it's a range (A1..A2) elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and - !ereg("[0-9]",$this->_lookahead)) + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } - // If it's an external range like Sheet1!A1 or Sheet1:Sheet2!A1:B2 - elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead)) + // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } - // If it's an external range like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2 - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead)) + // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } @@ -1210,12 +1210,12 @@ class PHPExcel_Writer_Excel5_Parser return $token; } // If it's a string (of maximum 255 characters) - elseif (ereg("^\"[^\"]{0,255}\"$",$token)) + elseif (preg_match("/^\"[^\"]{0,255}\"$/",$token)) { return $token; } // if it's a function call - elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$token) and ($this->_lookahead == "(")) + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) { return $token; } @@ -1291,7 +1291,7 @@ class PHPExcel_Writer_Excel5_Parser function _expression() { // If it's a string return a string node - if (ereg("^\"[^\"]{0,255}\"$", $this->_current_token)) { + if (preg_match("/^\"[^\"]{0,255}\"$/", $this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; @@ -1388,21 +1388,21 @@ class PHPExcel_Writer_Excel5_Parser $this->_advance(); return $result; } - // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) - elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$this->_current_token)) + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } - // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$this->_current_token)) + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } - // if it's a range + // if it's a range A1:B2 or $A$1:$B$2 elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token) or preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token)) { @@ -1410,17 +1410,21 @@ class PHPExcel_Writer_Excel5_Parser $this->_advance(); return $result; } - // If it's an external range (Sheet1!A1 or Sheet1!A1:B2) - elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$this->_current_token)) + // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) + elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) { - $result = $this->_current_token; + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } - // If it's an external range ('Sheet1'!A1 or 'Sheet1'!A1:B2) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$this->_current_token)) + // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) { - $result = $this->_current_token; + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } @@ -1431,7 +1435,7 @@ class PHPExcel_Writer_Excel5_Parser return $result; } // if it's a function call - elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$this->_current_token)) + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token)) { $result = $this->_func(); return $result; diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php index ba359d311..bdae49f5c 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Workbook (used as the base for this class): @@ -90,6 +90,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContaine /** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php'; +/** PHPExcel_Worksheet */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; + /** PHPExcel_Writer_Excel5_Xf */ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Xf.php'; @@ -111,7 +114,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Escher.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { @@ -165,11 +168,6 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ private $_phpExcel; - /** - * Color cache - */ - private $_colors = array(); - /** * Fonts writers * @@ -233,6 +231,11 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ private $_str_table; + /** + * Color cache + */ + private $_colors; + /** * Class constructor @@ -246,7 +249,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ public function __construct(PHPExcel $phpExcel = null, $BIFF_version = 0x0600, &$str_total, - &$str_unique, &$str_table, $parser, $tempDir = '' + &$str_unique, &$str_table, &$colors, $parser, $tempDir = '' ) { // It needs to call its parent's constructor explicitly @@ -261,6 +264,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $this->_str_total = &$str_total; $this->_str_unique = &$str_unique; $this->_str_table = &$str_table; + $this->_colors = &$colors; $this->_setPaletteXl97(); $this->_tmp_dir = $tempDir; @@ -287,6 +291,18 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $this->_parser->_references[] = $ref; // Register reference with parser } } + + // Build color cache + + // Sheet tab colors? + $countSheets = count($phpExcel->getAllSheets()); + for ($i = 0; $i < $countSheets; ++$i) { + $phpSheet = $phpExcel->getSheet($i); + if ($phpSheet->isTabColorSet()) { + $this->_addColor($phpSheet->getTabColor()->getRGB()); + } + } + } /** @@ -302,13 +318,6 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $xfWriter->setBIFFVersion($this->_BIFF_version); $xfWriter->setIsStyleXf($isStyleXf); - $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); - $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); - $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); - $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); - $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); - $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); - // Add the font if not already added $fontHashCode = $style->getFont()->getHashCode(); @@ -329,6 +338,15 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // Assign the font index to the xf record $xfWriter->setFontIndex($fontIndex); + // Background colors, best to treat these after the font so black will come after white in custom palette + $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); + $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); + $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); + $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); + $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); + $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); + $xfWriter->setDiagColor($this->_addColor($style->getBorders()->getDiagonal()->getColor()->getRGB())); + // Add the number format if it is not a built-in one and not already added if ($style->getNumberFormat()->getBuiltInFormatCode() === false) { $numberFormatHashCode = $style->getNumberFormat()->getHashCode(); @@ -509,7 +527,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // Add part 2 of the Workbook globals, the SHEET records $this->_calcSheetOffsets(); for ($i = 0; $i < $total_worksheets; ++$i) { - $this->_storeBoundsheet($this->_phpExcel->getSheet($i)->getTitle(), $this->_worksheetOffsets[$i]); + $this->_storeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); } // Add part 3 of the Workbook globals @@ -717,6 +735,34 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { $chunk = ''; + // Named ranges + if (count($this->_phpExcel->getNamedRanges()) > 0) { + // Loop named ranges + $namedRanges = $this->_phpExcel->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + + // Create absolute coordinate + $range = PHPExcel_Cell::splitRange($namedRange->getRange()); + for ($i = 0; $i < count($range); $i++) { + $range[$i][0] = '\'' . str_replace("'", "''", $namedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteCoordinate($range[$i][0]); + if (isset($range[$i][1])) { + $range[$i][1] = PHPExcel_Cell::absoluteCoordinate($range[$i][1]); + } + } + $range = PHPExcel_Cell::buildRange($range); // e.g. Sheet1!$A$1:$B$2 + + // parse formula + try { + $error = $this->_parser->parse($range); + $formulaData = $this->_parser->toReversePolish(); + $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, 0, false)); + + } catch(Exception $e) { + // do nothing + } + } + } + // total number of sheets $total_worksheets = count($this->_phpExcel->getAllSheets()); @@ -775,19 +821,28 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // write the print areas, if any for ($i = 0; $i < $total_worksheets; ++$i) { if ($this->_phpExcel->getSheet($i)->getPageSetup()->isPrintAreaSet()) { - // Print area + // Print area, e.g. A3:J6,H1:X20 $printArea = PHPExcel_Cell::splitRange($this->_phpExcel->getSheet($i)->getPageSetup()->getPrintArea()); - $printArea = $printArea[0]; - $printArea[0] = PHPExcel_Cell::coordinateFromString($printArea[0]); - $printArea[1] = PHPExcel_Cell::coordinateFromString($printArea[1]); - - $print_rowmin = $printArea[0][1] - 1; - $print_rowmax = $printArea[1][1] - 1; - $print_colmin = PHPExcel_Cell::columnIndexFromString($printArea[0][0]) - 1; - $print_colmax = PHPExcel_Cell::columnIndexFromString($printArea[1][0]) - 1; + $countPrintArea = count($printArea); - // construct formula data manually because parser does not recognize absolute 3d cell references - $formulaData = pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); + $formulaData = ''; + for ($j = 0; $j < $countPrintArea; ++$j) { + $printAreaRect = $printArea[$j]; // e.g. A3:J6 + $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); + + $print_rowmin = $printAreaRect[0][1] - 1; + $print_rowmax = $printAreaRect[1][1] - 1; + $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; + $print_colmax = PHPExcel_Cell::columnIndexFromString($printAreaRect[1][0]) - 1; + + // construct formula data manually because parser does not recognize absolute 3d cell references + $formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); + + if ($j > 0) { + $formulaData .= pack('C', 0x10); // list operator token ',' + } + } // store the DEFINEDNAME record $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x06), $formulaData, $i + 1, true)); @@ -886,21 +941,34 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Writes Excel BIFF BOUNDSHEET record. * - * @param string $sheetname Worksheet name + * @param PHPExcel_Worksheet $sheet Worksheet name * @param integer $offset Location of worksheet BOF * @access private */ - function _storeBoundsheet($sheetname,$offset) + function _storeBoundsheet($sheet, $offset) { + $sheetname = $sheet->getTitle(); $record = 0x0085; // Record identifier + + // sheet state + switch ($sheet->getSheetState()) { + case PHPExcel_Worksheet::SHEETSTATE_VISIBLE: $ss = 0x00; break; + case PHPExcel_Worksheet::SHEETSTATE_HIDDEN: $ss = 0x01; break; + case PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN: $ss = 0x02; break; + default: $ss = 0x00; break; + } + + // sheet type + $st = 0x00; + $grbit = 0x0000; // Visibility and sheet type if ($this->_BIFF_version == 0x0600) { - $data = pack("Vv", $offset, $grbit); + $data = pack("VCC", $offset, $ss, $st); $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheetname); } else { $cch = strlen($sheetname); // Length of sheet name - $data = pack("VvC", $offset, $grbit, $cch); + $data = pack("VCCC", $offset, $ss, $st, $cch); $data .= $sheetname; } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php index 079947437..831740964 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class): @@ -69,6 +69,9 @@ if (!defined('PHPEXCEL_ROOT')) { define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); } +/** PHPExcel_Cell_DataType */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; + /** PHPExcel_Writer_Excel5_Parser.php */ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Parser.php'; @@ -81,6 +84,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Escher.php'; /** PHPExcel_RichText */ require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; +/** PHPExcel_Shared_Font */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; + /** PHPExcel_Shared_String */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; @@ -105,7 +111,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/S * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter { @@ -194,6 +200,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter */ var $_str_table; + /** + * Color cache + */ + private $_colors; + /** * The temporary dir for storing files * @var string @@ -256,8 +267,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter */ public function __construct($BIFF_version, &$str_total, - &$str_unique, &$str_table, - $parser, $tempDir = '', $phpSheet) + &$str_unique, &$str_table, &$colors, + $parser, $tempDir = '', $preCalculateFormulas, $phpSheet) { // It needs to call its parent's constructor explicitly parent::__construct(); @@ -269,9 +280,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } + $this->_preCalculateFormulas = $preCalculateFormulas; $this->_str_total = &$str_total; $this->_str_unique = &$str_unique; $this->_str_table = &$str_table; + $this->_colors = &$colors; $this->_parser = $parser; $this->_phpSheet = $phpSheet; @@ -378,12 +391,14 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Column dimensions $columnDimensions = $this->_phpSheet->getColumnDimensions(); for ($i = 0; $i < 256; ++$i) { - $width = 9.140625; // assuming Calibri 11 $hidden = 0; $level = 0; + $xfIndex = 15; // there are 15 cell style Xfs if ($this->_phpSheet->getDefaultColumnDimension()->getWidth() >= 0) { $width = $this->_phpSheet->getDefaultColumnDimension()->getWidth(); + } else { + $width = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($this->_phpSheet->getParent()->getDefaultStyle()->getFont()); } $columnLetter = PHPExcel_Cell::stringFromColumnIndex($i); @@ -394,9 +409,10 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } $hidden = $columnDimension->getVisible() ? 0 : 1; $level = $columnDimension->getOutlineLevel(); + $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs } - $this->_setColumn( $i, $i, $width, null, $hidden, $level); + $this->_setColumn( $i, $i, $width, $xfIndex, $hidden, $level); } // Write the COLINFO records if they exist @@ -472,12 +488,24 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Write sheet protection $this->_storeProtect(); + // Write SCENPROTECT + $this->_writeScenProtect(); + + // Write OBJECTPROTECT + $this->_writeObjectProtect(); + // Write sheet password $this->_storePassword(); // Write sheet dimensions $this->_storeDimensions(); + // Row dimensions + foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { + $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs + $this->_setRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); + } + // Write Cells foreach ($this->_phpSheet->getCellCollection() as $cell) { $row = $cell->getRow() - 1; @@ -505,7 +533,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter break; case PHPExcel_Cell_DataType::TYPE_FORMULA: - $this->_writeFormula($row, $column, $cell->getValue(), $xfIndex); + $calculatedValue = $this->_preCalculateFormulas ? + $cell->getCalculatedValue() : null; + $this->_writeFormula($row, $column, $cell->getValue(), $xfIndex, $calculatedValue); break; case PHPExcel_Cell_DataType::TYPE_BOOL: @@ -520,19 +550,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_writeNumber($row, $column, $cell->getValue(), $xfIndex); break; } - - // Hyperlink? - if ($cell->hasHyperlink()) { - $this->_writeUrl($row, $column, str_replace('sheet://', 'internal:', $cell->getHyperlink()->getUrl())); - } } } - // Row dimensions - foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { - $this->_setRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), null, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); - } - // Append if ($this->_BIFF_version == 0x0600) { $this->_storeMsoDrawing(); @@ -542,13 +562,40 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($this->_phpSheet->getFreezePane()) { $this->_storePanes(); } - $this->_storeSelection($this->_selection); + $this->_storeSelection(); $this->_storeMergedCells(); + + // Hyperlinks + if ($this->_BIFF_version == 0x0600) { + foreach ($this->_phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinate); + + $url = $hyperlink->getUrl(); + + if ( strpos($url, 'sheet://') !== false ) { + // internal to current workbook + $url = str_replace('sheet://', 'internal:', $url); + + } else if ( preg_match('/^(http:|https:|ftp:|mailto:)/', $url) ) { + // URL + // $url = $url; + + } else { + // external (local file) + $url = 'external:' . $url; + } + + $this->_writeUrl($row - 1, PHPExcel_Cell::columnIndexFromString($column) - 1, $url); + } + } + /*if ($this->_BIFF_version == 0x0600) { $this->_storeDataValidity(); }*/ if ($this->_BIFF_version == 0x0600) { + $this->_storeSheetLayout(); + $this->_writeSheetProtection(); $this->_storeRangeProtection(); } @@ -627,32 +674,18 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $firstcol first column on the range * @param integer $lastcol last column on the range * @param integer $width width to set - * @param mixed $format The optional XF format to apply to the columns + * @param integer $xfIndex The optional cell style Xf index to apply to the columns * @param integer $hidden The optional hidden atribute * @param integer $level The optional outline level */ - private function _setColumn($firstcol, $lastcol, $width, $format = null, $hidden = 0, $level = 0) + private function _setColumn($firstcol, $lastcol, $width, $xfIndex = 15, $hidden = 0, $level = 0) { - $this->_colinfo[] = array($firstcol, $lastcol, $width, &$format, $hidden, $level); + $this->_colinfo[] = array($firstcol, $lastcol, $width, $xfIndex, $hidden, $level); // Set width to zero if column is hidden $width = ($hidden) ? 0 : $width; } - /** - * Set which cell or cells are selected in a worksheet - * - * @access public - * @param integer $first_row first row in the selected quadrant - * @param integer $first_column first column in the selected quadrant - * @param integer $last_row last row in the selected quadrant - * @param integer $last_column last column in the selected quadrant - */ - function setSelection($first_row,$first_column,$last_row,$last_column) - { - $this->_selection = array($first_row,$first_column,$last_row,$last_column); - } - /** * Set the option to print the row and column headers on the printed page. * @@ -913,18 +946,56 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $col Zero indexed column * @param string $formula The formula text string * @param mixed $format The optional XF format + * @param mixed $calculatedValue Calculated value * @return integer */ - private function _writeFormula($row, $col, $formula, $xfIndex) + private function _writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) { $record = 0x0006; // Record identifier - // Excel normally stores the last calculated value of the formula in $num. - // Clearly we are not in a position to calculate this a priori. Instead - // we set $num to zero and set the option flags in $grbit to ensure - // automatic calculation of the formula when the file is opened. - // - $num = 0x00; // Current value of formula + // Initialize possible additional value for STRING record that should be written after the FORMULA record? + $stringValue = null; + + // calculated value + if (isset($calculatedValue)) { + + // Since we can't yet get the data type of the calculated value, + // we use best effort to determine data type + + if (is_bool($calculatedValue)) { + // Boolean value + $num = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); + + } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { + // Numeric value + $num = pack('d', $calculatedValue); + + } elseif (is_string($calculatedValue)) { + if (array_key_exists($calculatedValue, PHPExcel_Cell_DataType::getErrorCodes())) { + // Error value + $num = pack('CCCvCv', 0x02, 0x00, $this->_mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); + + } elseif ($calculatedValue === '' && $this->_BIFF_version == 0x0600) { + // Empty string (and BIFF8) + $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + + } else { + // Non-empty string value (or empty string BIFF5) + $stringValue = $calculatedValue; + $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + + } + + } else { + // We are really not supposed to reach here + $num = pack('d', 0x00); + + } + + } else { + $num = pack('d', 0x00); + } + $grbit = 0x03; // Option flags $unknown = 0x0000; // Must be zero @@ -948,9 +1019,17 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $length = 0x16 + $formlen; // Length of the record data $header = pack("vv", $record, $length); - $data = pack("vvvdvVv", $row, $col, $xfIndex, $num, - $grbit, $unknown, $formlen); + + $data = pack("vvv", $row, $col, $xfIndex) + . $num + . pack("vVv", $grbit, $unknown, $formlen); $this->_append($header . $data . $formula); + + // Append also a STRING record if necessary + if ($stringValue !== null) { + $this->_writeStringRecord($stringValue); + } + return 0; } catch (Exception $e) { @@ -959,6 +1038,22 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } + /** + * Write a STRING record. This + * + * @param string $stringValue + */ + private function _writeStringRecord($stringValue) + { + $record = 0x0207; // Record identifier + $data = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($stringValue); + + $length = strlen($data); + $header = pack('vv', $record, $length); + + $this->_append($header . $data); + } + /** * Write a hyperlink. * This is comprised of two elements: the visible label and @@ -1148,40 +1243,21 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // relative if link starts with up-dir, "..\..\somefile.xls" // otherwise, absolute - $absolute = 0x02; // Bit mask - if (!preg_match("/\\\/", $url)) { - $absolute = 0x00; - } - if (preg_match("/^\.\.\\\/", $url)) { - $absolute = 0x00; + $absolute = 0x00; // relative path + if ( preg_match('/^[A-Z]:/', $url) ) { + $absolute = 0x02; // absolute path on Windows, e.g. C:\... } $link_type = 0x01 | $absolute; // Determine if the link contains a sheet reference and change some of the // parameters accordingly. // Split the dir name and sheet name (if it exists) - /*if (preg_match("/\#/", $url)) { - list($dir_long, $sheet) = split("\#", $url); - } else { - $dir_long = $url; - } - - if (isset($sheet)) { - $link_type |= 0x08; - $sheet_len = pack("V", strlen($sheet) + 0x01); - $sheet = join("\0", split('', $sheet)); - $sheet .= "\0\0\0"; - } else { - $sheet_len = ''; - $sheet = ''; - }*/ $dir_long = $url; if (preg_match("/\#/", $url)) { $link_type |= 0x08; } - // Pack the link type $link_type = pack("V", $link_type); @@ -1193,7 +1269,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0"; // Store the long dir name as a wchar string (non-null terminated) - //$dir_long = join("\0", split('', $dir_long)); $dir_long = $dir_long . "\0"; // Pack the lengths of the dir strings @@ -1238,11 +1313,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $row The row to set * @param integer $height Height we are giving to the row. * Use null to set XF without setting height - * @param mixed $format XF format we are giving to the row + * @param integer $xfIndex The optional cell style Xf index to apply to the columns * @param bool $hidden The optional hidden attribute * @param integer $level The optional outline level for row, in range [0,7] */ - private function _setRow($row, $height, $format = null, $hidden = false, $level = 0) + private function _setRow($row, $height, $xfIndex, $hidden = false, $level = 0) { $record = 0x0208; // Record identifier $length = 0x0010; // Number of bytes to follow @@ -1252,7 +1327,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $irwMac = 0x0000; // Used by Excel to optimise loading $reserved = 0x0000; // Reserved $grbit = 0x0000; // Option flags - $ixfe = 0x0F; // hard-coding XF index + $ixfe = $xfIndex; if ( $height < 0 ){ $height = null; @@ -1275,8 +1350,10 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($hidden) { $grbit |= 0x0020; } - $grbit |= 0x0040; // fUnsynced - if ($format) { + if ($height !== null) { + $grbit |= 0x0040; // fUnsynced + } + if ($xfIndex !== 0xF) { $grbit |= 0x0080; } $grbit |= 0x0100; @@ -1451,9 +1528,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $coldx = 8.43; } if (isset($col_array[3])) { - $format = $col_array[3]; + $xfIndex = $col_array[3]; } else { - $format = 0; + $xfIndex = 15; } if (isset($col_array[4])) { $grbit = $col_array[4]; @@ -1470,7 +1547,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $coldx *= 256; // Convert to units of 1/256 of a char - $ixfe = 0x0F; // hard-coding XF index + $ixfe = $xfIndex; $reserved = 0x00; // Reserved $level = max(0, min($level, 7)); @@ -1486,12 +1563,39 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * Write BIFF record SELECTION. * * @access private - * @param array $array array containing ($rwFirst,$colFirst,$rwLast,$colLast) - * @see setSelection() */ - function _storeSelection($array) + function _storeSelection() { - list($rwFirst,$colFirst,$rwLast,$colLast) = $array; + // look up the selected cell range + $selectedCells = $this->_phpSheet->getSelectedCells(); + $selectedCells = PHPExcel_Cell::splitRange($this->_phpSheet->getSelectedCells()); + $selectedCells = $selectedCells[0]; + if (count($selectedCells) == 2) { + list($first, $last) = $selectedCells; + } else { + $first = $selectedCells[0]; + $last = $selectedCells[0]; + } + + list($colFirst, $rwFirst) = PHPExcel_Cell::coordinateFromString($first); + $colFirst = PHPExcel_Cell::columnIndexFromString($colFirst) - 1; // base 0 column index + --$rwFirst; // base 0 row index + + list($colLast, $rwLast) = PHPExcel_Cell::coordinateFromString($last); + $colLast = PHPExcel_Cell::columnIndexFromString($colLast) - 1; // base 0 column index + --$rwLast; // base 0 row index + + // make sure we are not out of bounds + $colFirst = min($colFirst, 255); + $colLast = min($colLast, 255); + if ($this->_BIFF_version == 0x0600) { + $rwFirst = min($rwFirst, 65535); + $rwLast = min($rwLast, 65535); + } else { + $rwFirst = min($rwFirst, 16383); + $rwLast = min($rwLast, 16383); + } + $record = 0x001D; // Record identifier $length = 0x000F; // Number of bytes to follow @@ -1585,6 +1689,77 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } } + /** + * Write SHEETLAYOUT record + */ + private function _storeSheetLayout() + { + if (!$this->_phpSheet->isTabColorSet()) { + return; + } + + $recordData = pack( + 'vvVVVvv' + , 0x0862 + , 0x0000 // unused + , 0x00000000 // unused + , 0x00000000 // unused + , 0x00000014 // size of record data + , $this->_colors[$this->_phpSheet->getTabColor()->getRGB()] // color index + , 0x0000 // unused + ); + + $length = strlen($recordData); + + $record = 0x0862; // Record identifier + $header = pack('vv', $record, $length); + $this->_append($header . $recordData); + } + + /** + * Write SHEETPROTECTION + */ + private function _writeSheetProtection() + { + // record identifier + $record = 0x0867; + + // prepare options + $options = (int) !$this->_phpSheet->getProtection()->getObjects() + | (int) !$this->_phpSheet->getProtection()->getScenarios() << 1 + | (int) !$this->_phpSheet->getProtection()->getFormatCells() << 2 + | (int) !$this->_phpSheet->getProtection()->getFormatColumns() << 3 + | (int) !$this->_phpSheet->getProtection()->getFormatRows() << 4 + | (int) !$this->_phpSheet->getProtection()->getInsertColumns() << 5 + | (int) !$this->_phpSheet->getProtection()->getInsertRows() << 6 + | (int) !$this->_phpSheet->getProtection()->getInsertHyperlinks() << 7 + | (int) !$this->_phpSheet->getProtection()->getDeleteColumns() << 8 + | (int) !$this->_phpSheet->getProtection()->getDeleteRows() << 9 + | (int) !$this->_phpSheet->getProtection()->getSelectLockedCells() << 10 + | (int) !$this->_phpSheet->getProtection()->getSort() << 11 + | (int) !$this->_phpSheet->getProtection()->getAutoFilter() << 12 + | (int) !$this->_phpSheet->getProtection()->getPivotTables() << 13 + | (int) !$this->_phpSheet->getProtection()->getSelectUnlockedCells() << 14 ; + + // record data + $recordData = pack( + 'vVVCVVvv' + , 0x0867 // repeated record identifier + , 0x0000 // not used + , 0x0000 // not used + , 0x00 // not used + , 0x01000200 // unknown data + , 0xFFFFFFFF // unknown data + , $options // options + , 0x0000 // not used + ); + + $length = strlen($recordData); + $header = pack('vv', $record, $length); + + $this->_append($header . $recordData); + } + /** * Write BIFF record RANGEPROTECTION * @@ -2156,7 +2331,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($this->_phpSheet->getShowSummaryRight()) { $grbit |= 0x0080; // Outline summary right } - if ($this->_phpSheet->getPageSetup()->getFitToWidth() || $this->_phpSheet->getPageSetup()->getFitToHeight()) { + if ($this->_phpSheet->getPageSetup()->getFitToPage()) { $grbit |= 0x0100; // Page setup fit to page } if ($this->_outline_on) { @@ -2292,6 +2467,54 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_append($header.$data); } + /** + * Write SCENPROTECT + */ + private function _writeScenProtect() + { + // Exit if sheet protection is not active + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + // Exit if scenarios are not protected + if (!$this->_phpSheet->getProtection()->getScenarios()) { + return; + } + + $record = 0x00DD; // Record identifier + $length = 0x0002; // Bytes to follow + + $header = pack('vv', $record, $length); + $data = pack('v', 1); + + $this->_append($header . $data); + } + + /** + * Write OBJECTPROTECT + */ + private function _writeObjectProtect() + { + // Exit if sheet protection is not active + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + // Exit if objects are not protected + if (!$this->_phpSheet->getProtection()->getObjects()) { + return; + } + + $record = 0x0063; // Record identifier + $length = 0x0002; // Bytes to follow + + $header = pack('vv', $record, $length); + $data = pack('v', 1); + + $this->_append($header . $data); + } + /** * Write the worksheet PASSWORD record. * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php index 717866330..be8d11ad8 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Format (used as the base for this class): @@ -87,7 +87,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Xf { @@ -234,7 +234,7 @@ class PHPExcel_Writer_Excel5_Xf if ($this->_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) == 0) { $this->_left_color = 0; } - if ($this->_diag == 0) { + if ($this->_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { $this->_diag_color = 0; } @@ -302,15 +302,19 @@ class PHPExcel_Writer_Excel5_Xf $border1 |= $this->_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) << 12; $border1 |= $this->_left_color << 16; $border1 |= $this->_right_color << 23; - $diag_tl_to_rb = 0; - $diag_tr_to_lb = 0; + + $diagonalDirection = $this->_style->getBorders()->getDiagonalDirection(); + $diag_tl_to_rb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_DOWN; + $diag_tr_to_lb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_UP; $border1 |= $diag_tl_to_rb << 30; $border1 |= $diag_tr_to_lb << 31; $border2 = $this->_top_color; // Border color $border2 |= $this->_bottom_color << 7; $border2 |= $this->_diag_color << 14; - $border2 |= $this->_diag << 21; + $border2 |= $this->_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) << 21; $border2 |= $this->_mapFillType($this->_style->getFill()->getFillType()) << 26; $header = pack("vv", $record, $length); @@ -395,6 +399,17 @@ class PHPExcel_Writer_Excel5_Xf $this->_right_color = $colorIndex; } + /** + * Sets the cell's diagonal border color + * + * @access public + * @param int $colorIndex Color index + */ + function setDiagColor($colorIndex) + { + $this->_diag_color = $colorIndex; + } + /** * Sets the cell's foreground color diff --git a/libraries/PHPExcel/PHPExcel/Writer/HTML.php b/libraries/PHPExcel/PHPExcel/Writer/HTML.php index d1f59a1de..4ac8c73a6 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/HTML.php +++ b/libraries/PHPExcel/PHPExcel/Writer/HTML.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { /** @@ -111,11 +111,39 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { private $_columnWidths = null; /** - * Default font size + * Default font * - * @var int + * @var PHPExcel_Style_Font */ - private $_defaultFontSize; + private $_defaultFont; + + /** + * Flag whether spans have been calculated + * + * @var boolean + */ + private $_spansAreCalculated; + + /** + * Excel cells that should not be written as HTML cells + * + * @var array + */ + private $_isSpannedCell; + + /** + * Excel cells that are upper-left corner in a cell merge + * + * @var array + */ + private $_isBaseCell; + + /** + * Excel rows that should not be written as HTML rows + * + * @var array + */ + private $_isSpannedRow; /** * Is the current writer creating PDF? @@ -131,9 +159,14 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { */ public function __construct(PHPExcel $phpExcel) { $this->_phpExcel = $phpExcel; - $this->_defaultFontSize = $this->_phpExcel->getDefaultStyle()->getFont()->getSize(); + $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont(); $this->_sheetIndex = 0; $this->_imagesRoot = '.'; + + $this->_spansAreCalculated = false; + $this->_isSpannedCell = array(); + $this->_isBaseCell = array(); + $this->_isSpannedRow = array(); } /** @@ -210,6 +243,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { case PHPExcel_Style_Border::BORDER_NONE: return '0px'; case PHPExcel_Style_Border::BORDER_DASHED: return '1px dashed'; case PHPExcel_Style_Border::BORDER_DOTTED: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DOUBLE: return '3px double'; case PHPExcel_Style_Border::BORDER_THICK: return '2px solid'; default: return '1px solid'; // map others to thin } @@ -286,6 +320,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { throw new Exception('Internal PHPExcel object not set to an instance of an object.'); } + // Ensure that Spans have been calculated? + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + // Fetch sheets $sheets = array(); if (is_null($this->_sheetIndex)) { @@ -300,9 +339,6 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Loop all sheets $sheetId = 0; foreach ($sheets as $sheet) { - // Get cell collection - $cellCollection = $sheet->getCellCollection(); - // Write table header $html .= $this->_generateTableHeader($sheet); @@ -313,13 +349,13 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; - // Loop trough cells + // Loop through cells $rowData = null; for ($row = $dimension[0][1]; $row <= $dimension[1][1]; ++$row) { // Start a new row $rowData = array(); - // Loop trough columns + // Loop through columns for ($column = $dimension[0][0]; $column <= $dimension[1][0]; ++$column) { // Cell exists? if ($sheet->cellExistsByColumnAndRow($column, $row)) { @@ -329,8 +365,10 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { } } - // Write row - $html .= $this->_generateRow($sheet, $rowData, $row - 1); + // Write row if there are HTML table cells in it + if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) { + $html .= $this->_generateRow($sheet, $rowData, $row - 1); + } } // Write table footer @@ -455,6 +493,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $this->_cssStyles; } + // Ensure that spans have been calculated + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + // Construct CSS $css = array(); @@ -523,7 +566,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // col elements, loop through columnDimensions and set width foreach ($sheet->getColumnDimensions() as $columnDimension) { - if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFontSize)) >= 0) { + if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) { $width = PHPExcel_Shared_Drawing::pixelsToPoints($width); $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1; $this->_columnWidths[$sheetIndex][$column] = $width; @@ -542,7 +585,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // table.sheetN tr { } $css['table.sheet' . $sheetIndex . ' tr'] = array(); - $pt_height = $rowDimension->getRowHeight(); + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; if ($rowDimension->getVisible() === false) { $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; @@ -556,7 +603,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // table.sheetN tr.rowYYYYYY { } $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array(); - $pt_height = $rowDimension->getRowHeight(); + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; if ($rowDimension->getVisible() === false) { $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; @@ -822,7 +873,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Value if ($cell->getValue() instanceof PHPExcel_RichText) { - // Loop trough rich text elements + // Loop through rich text elements $elements = $cell->getValue()->getRichTextElements(); foreach ($elements as $element) { // Rich text start? @@ -854,17 +905,16 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { if ($this->_preCalculateFormulas) { $cellData = PHPExcel_Style_NumberFormat::toFormattedString( $cell->getCalculatedValue(), - $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode() + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') ); } else { $cellData = PHPExcel_Style_NumberFormat::ToFormattedString( $cell->getValue(), - $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode() + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') ); } - - // Convert UTF8 data to PCDATA - $cellData = htmlspecialchars($cellData); } // replace leading spaces on each line with   @@ -910,19 +960,17 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $cellData = '' . $cellData . ''; } - // Column/rowspan - foreach ($pSheet->getMergeCells() as $cells) { - if ($cell->isInRange($cells)) { - list($first, ) = PHPExcel_Cell::splitRange($cells); + // Should the cell be written or is it swallowed by a rowspan or colspan? + $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]) + && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] ); - if ($first[0] == $cell->getCoordinate()) { - list($colSpan, $rowSpan) = PHPExcel_Cell::rangeDimension($cells); - } else { - $writeCell = false; - } - - break; - } + // Colspan and Rowspan + $colspan = 1; + $rowspan = 1; + if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) { + $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; + $rowSpan = $spans['rowspan']; + $colSpan = $spans['colspan']; } // Write @@ -1085,4 +1133,122 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $string; } + /** + * Add color to formatted string as inline style + * + * @param string $pValue Plain formatted value without color + * @param string $pFormat Format code + * @return string + */ + public function formatColor($pValue, $pFormat) + { + // Color information, e.g. [Red] is always at the beginning + $color = null; // initialize + $matches = array(); + + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + if (preg_match($color_regex, $pFormat, $matches)) { + $color = str_replace('[', '', $matches[0]); + $color = str_replace(']', '', $color); + $color = strtolower($color); + } + + // convert to PCDATA + $value = htmlspecialchars($pValue); + + // color span tag + if ($color !== null) { + $value = '' . $value . ''; + } + + return $value; + } + + /** + * Calculate information about HTML colspan and rowspan which is not always the same as Excel's + */ + private function _calculateSpans() + { + // Identify all cells that should be omitted in HTML due to cell merge. + // In HTML only the upper-left cell should be written and it should have + // appropriate rowspan / colspan attribute + $sheetIndexes = $this->_sheetIndex !== null ? + array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1); + + foreach ($sheetIndexes as $sheetIndex) { + $sheet = $this->_phpExcel->getSheet($sheetIndex); + + $candidateSpannedRow = array(); + + // loop through all Excel merged cells + foreach ($sheet->getMergeCells() as $cells) { + list($cells, ) = PHPExcel_Cell::splitRange($cells); + $first = $cells[0]; + $last = $cells[1]; + + list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first); + $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1; + + list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last); + $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; + + // loop through the individual cells in the individual merge + for ($r = $fr; $r <= $lr; ++$r) { + // also, flag this row as a HTML row that is candidate to be omitted + $candidateSpannedRow[$r] = $r; + + for ($c = $fc; $c <= $lc; ++$c) { + if ( !($c == $fc && $r == $fr) ) { + // not the upper-left cell (should not be written in HTML) + $this->_isSpannedCell[$sheetIndex][$r][$c] = array( + 'baseCell' => array($fr, $fc), + ); + } else { + // upper-left is the base cell that should hold the colspan/rowspan attribute + $this->_isBaseCell[$sheetIndex][$r][$c] = array( + 'xlrowspan' => $lr - $fr + 1, // Excel rowspan + 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change + 'xlcolspan' => $lc - $fc + 1, // Excel colspan + 'colspan' => $lc - $fc + 1, // HTML colspan, value may change + ); + } + } + } + } + + // Identify which rows should be omitted in HTML. These are the rows where all the cells + // participate in a merge and the where base cells are somewhere above. + $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()); + foreach ($candidateSpannedRow as $rowIndex) { + if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) { + if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { + $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; + }; + } + } + + // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 + if ( isset($this->_isSpannedRow[$sheetIndex]) ) { + foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { + $adjustedBaseCells = array(); + for ($c = 0; $c < $countColumns; ++$c) { + $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; + + if ( !in_array($baseCell, $adjustedBaseCells) ) { + + // subtract rowspan by 1 + --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan']; + $adjustedBaseCells[] = $baseCell; + } + } + } + } + + // TODO: Same for columns + } + + // We have calculated the spans + $this->_spansAreCalculated = true; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Writer/IWriter.php b/libraries/PHPExcel/PHPExcel/Writer/IWriter.php index b8f0ba89f..063d755e7 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/IWriter.php +++ b/libraries/PHPExcel/PHPExcel/Writer/IWriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Writer_IWriter { diff --git a/libraries/PHPExcel/PHPExcel/Writer/PDF.php b/libraries/PHPExcel/PHPExcel/Writer/PDF.php index 6712c3929..cf2825d56 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/PDF.php +++ b/libraries/PHPExcel/PHPExcel/Writer/PDF.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,6 +49,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; /** PHPExcel_Shared_Drawing */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; +/** PHPExcel_Shared_File */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; + /** PHPExcel_HashTable */ require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; @@ -61,7 +64,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PDF.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_PDF extends PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { /** @@ -79,7 +82,7 @@ class PHPExcel_Writer_PDF extends PHPExcel_Writer_HTML implements PHPExcel_Write public function __construct(PHPExcel $phpExcel) { parent::__construct($phpExcel); $this->setUseInlineCss(true); - $this->_tempDir = sys_get_temp_dir(); + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); } /** @@ -129,7 +132,13 @@ class PHPExcel_Writer_PDF extends PHPExcel_Writer_HTML implements PHPExcel_Write $pdf->setPrintHeader(false); $pdf->setPrintFooter(false); $pdf->AddPage(); + + // Set the appropriate font $pdf->SetFont('freesans'); + //$pdf->SetFont('arialunicid0-chinese-simplified'); + //$pdf->SetFont('arialunicid0-chinese-traditional'); + //$pdf->SetFont('arialunicid0-korean'); + //$pdf->SetFont('arialunicid0-japanese'); $pdf->writeHTML($html); // Document info diff --git a/libraries/PHPExcel/PHPExcel/Writer/Serialized.php b/libraries/PHPExcel/PHPExcel/Writer/Serialized.php index 940a49969..d831b8eb1 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Serialized.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Serialized.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Serialized implements PHPExcel_Writer_IWriter { @@ -190,10 +190,10 @@ class PHPExcel_Writer_Serialized implements PHPExcel_Writer_IWriter // PHPExcel $objWriter->startElement('PHPExcel'); - $objWriter->writeAttribute('version', '1.7.0'); + $objWriter->writeAttribute('version', '1.7.2'); // Comment - $objWriter->writeComment('This file has been generated using PHPExcel v1.7.0 (http://www.codeplex.com/PHPExcel). It contains a base64 encoded serialized version of the PHPExcel internal object.'); + $objWriter->writeComment('This file has been generated using PHPExcel v1.7.2 (http://www.codeplex.com/PHPExcel). It contains a base64 encoded serialized version of the PHPExcel internal object.'); // Data $objWriter->startElement('data'); From f26783ab3a3e8635a6dfa0ee9d3c7e188b6d4f9f Mon Sep 17 00:00:00 2001 From: Dieter Adriaenssens Date: Sun, 2 May 2010 21:40:37 +0200 Subject: [PATCH 3/6] PHPExcel : IBM AIX iconv() does not work --- libraries/PHPExcel/PHPExcel/Shared/String.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/PHPExcel/PHPExcel/Shared/String.php b/libraries/PHPExcel/PHPExcel/Shared/String.php index e165fdd63..bdd8b3faf 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/String.php +++ b/libraries/PHPExcel/PHPExcel/Shared/String.php @@ -122,9 +122,13 @@ class PHPExcel_Shared_String // we cannot use iconv when that happens // Also, sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) + // CUSTOM: IBM AIX iconv() does not work if (function_exists('iconv') && @iconv('UTF-8', 'UTF-16LE', 'x') - && @iconv_substr('A', 0, 1, 'UTF-8') ) { + && @iconv_substr('A', 0, 1, 'UTF-8') + && !(defined('PHP_OS') && @stristr(PHP_OS, 'AIX') + && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) + && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0))) { self::$_isIconvEnabled = true; } else { From 9c6e8bc186563887c364ba893d82def2840a3da3 Mon Sep 17 00:00:00 2001 From: Dieter Adriaenssens Date: Tue, 25 May 2010 22:10:48 +0200 Subject: [PATCH 4/6] Update library PHPExcel to version 1.7.3 --- ChangeLog | 1 + libraries/PHPExcel/PHPExcel.php | 132 +-- libraries/PHPExcel/PHPExcel/Autoloader.php | 51 + .../PHPExcel/CachedObjectStorage/APC.php | 193 ++++ .../CachedObjectStorage/CacheBase.php | 162 +++ .../PHPExcel/CachedObjectStorage/DiscISAM.php | 143 +++ .../PHPExcel/CachedObjectStorage/ICache.php | 97 ++ .../PHPExcel/CachedObjectStorage/Memcache.php | 209 ++++ .../PHPExcel/CachedObjectStorage/Memory.php | 85 ++ .../CachedObjectStorage/MemoryGZip.php | 107 ++ .../CachedObjectStorage/MemorySerialized.php | 107 ++ .../PHPExcel/CachedObjectStorage/PHPTemp.php | 137 +++ .../PHPExcel/CachedObjectStorage/Wincache.php | 201 ++++ .../PHPExcel/CachedObjectStorageFactory.php | 131 +++ libraries/PHPExcel/PHPExcel/Calculation.php | 646 +++++++++--- .../PHPExcel/Calculation/Exception.php | 2 +- .../PHPExcel/Calculation/ExceptionHandler.php | 19 +- .../PHPExcel/Calculation/FormulaParser.php | 13 +- .../PHPExcel/Calculation/FormulaToken.php | 2 +- .../PHPExcel/Calculation/Function.php | 2 +- .../PHPExcel/Calculation/Functions.php | 893 +++++++++++++--- libraries/PHPExcel/PHPExcel/Cell.php | 103 +- .../PHPExcel/Cell/AdvancedValueBinder.php | 102 +- libraries/PHPExcel/PHPExcel/Cell/DataType.php | 16 +- .../PHPExcel/PHPExcel/Cell/DataValidation.php | 41 +- .../PHPExcel/Cell/DefaultValueBinder.php | 33 +- .../PHPExcel/PHPExcel/Cell/Hyperlink.php | 36 +- .../PHPExcel/PHPExcel/Cell/IValueBinder.php | 18 +- libraries/PHPExcel/PHPExcel/Comment.php | 80 +- .../PHPExcel/PHPExcel/DocumentProperties.php | 2 +- .../PHPExcel/PHPExcel/DocumentSecurity.php | 48 +- libraries/PHPExcel/PHPExcel/HashTable.php | 56 +- libraries/PHPExcel/PHPExcel/IComparable.php | 2 +- libraries/PHPExcel/PHPExcel/IOFactory.php | 148 +-- libraries/PHPExcel/PHPExcel/NamedRange.php | 56 +- libraries/PHPExcel/PHPExcel/Reader/CSV.php | 198 ++-- .../PHPExcel/Reader/DefaultReadFilter.php | 19 +- .../PHPExcel/PHPExcel/Reader/Excel2003XML.php | 34 +- .../PHPExcel/PHPExcel/Reader/Excel2007.php | 492 +++++---- libraries/PHPExcel/PHPExcel/Reader/Excel5.php | 982 +++++++++++------- .../PHPExcel/Reader/Excel5/Escher.php | 108 +- .../PHPExcel/PHPExcel/Reader/IReadFilter.php | 2 +- .../PHPExcel/PHPExcel/Reader/IReader.php | 2 +- libraries/PHPExcel/PHPExcel/Reader/OOCalc.php | 37 +- libraries/PHPExcel/PHPExcel/Reader/SYLK.php | 47 +- .../PHPExcel/PHPExcel/Reader/Serialized.php | 27 +- .../PHPExcel/PHPExcel/ReferenceHelper.php | 57 +- libraries/PHPExcel/PHPExcel/RichText.php | 125 +-- .../PHPExcel/RichText/ITextElement.php | 32 +- libraries/PHPExcel/PHPExcel/RichText/Run.php | 42 +- .../PHPExcel/RichText/TextElement.php | 41 +- libraries/PHPExcel/PHPExcel/Settings.php | 65 ++ .../PHPExcel/PHPExcel/Shared/CodePage.php | 94 ++ libraries/PHPExcel/PHPExcel/Shared/Date.php | 53 +- .../PHPExcel/PHPExcel/Shared/Drawing.php | 127 ++- libraries/PHPExcel/PHPExcel/Shared/Escher.php | 2 +- .../PHPExcel/Shared/Escher/DgContainer.php | 2 +- .../Escher/DgContainer/SpgrContainer.php | 2 +- .../DgContainer/SpgrContainer/SpContainer.php | 2 +- .../PHPExcel/Shared/Escher/DggContainer.php | 2 +- .../Escher/DggContainer/BstoreContainer.php | 2 +- .../DggContainer/BstoreContainer/BSE.php | 2 +- .../DggContainer/BstoreContainer/BSE/Blip.php | 2 +- libraries/PHPExcel/PHPExcel/Shared/Excel5.php | 21 +- libraries/PHPExcel/PHPExcel/Shared/File.php | 2 +- libraries/PHPExcel/PHPExcel/Shared/Font.php | 77 +- .../PHPExcel/PHPExcel/Shared/JAMA/Matrix.php | 27 +- libraries/PHPExcel/PHPExcel/Shared/OLE.php | 30 +- .../Shared/OLE/ChainedBlockStream.php | 16 +- .../PHPExcel/PHPExcel/Shared/OLE/PPS.php | 218 ++++ .../PHPExcel/PHPExcel/Shared/OLE/PPS/File.php | 84 ++ .../PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php | 447 ++++++++ .../PHPExcel/PHPExcel/Shared/OLERead.php | 59 +- .../PHPExcel/Shared/PasswordHasher.php | 2 +- libraries/PHPExcel/PHPExcel/Shared/String.php | 281 ++++- .../PHPExcel/PHPExcel/Shared/XMLWriter.php | 2 +- .../PHPExcel/Shared/ZipStreamWrapper.php | 27 +- .../PHPExcel/Shared/trend/bestFitClass.php | 2 +- .../Shared/trend/exponentialBestFitClass.php | 10 +- .../Shared/trend/linearBestFitClass.php | 10 +- .../Shared/trend/logarithmicBestFitClass.php | 10 +- .../Shared/trend/polynomialBestFitClass.php | 10 +- .../Shared/trend/powerBestFitClass.php | 10 +- .../PHPExcel/Shared/trend/trendClass.php | 8 - libraries/PHPExcel/PHPExcel/Style.php | 85 +- .../PHPExcel/PHPExcel/Style/Alignment.php | 74 +- libraries/PHPExcel/PHPExcel/Style/Border.php | 51 +- libraries/PHPExcel/PHPExcel/Style/Borders.php | 77 +- libraries/PHPExcel/PHPExcel/Style/Color.php | 52 +- .../PHPExcel/PHPExcel/Style/Conditional.php | 73 +- libraries/PHPExcel/PHPExcel/Style/Fill.php | 61 +- libraries/PHPExcel/PHPExcel/Style/Font.php | 93 +- .../PHPExcel/PHPExcel/Style/NumberFormat.php | 342 +++--- .../PHPExcel/PHPExcel/Style/Protection.php | 14 +- libraries/PHPExcel/PHPExcel/Worksheet.php | 367 +++---- .../PHPExcel/Worksheet/BaseDrawing.php | 123 +-- .../PHPExcel/Worksheet/CellIterator.php | 38 +- .../PHPExcel/Worksheet/ColumnDimension.php | 2 +- .../PHPExcel/PHPExcel/Worksheet/Drawing.php | 51 +- .../PHPExcel/Worksheet/Drawing/Shadow.php | 75 +- .../PHPExcel/Worksheet/HeaderFooter.php | 102 +- .../Worksheet/HeaderFooterDrawing.php | 100 +- .../PHPExcel/Worksheet/MemoryDrawing.php | 67 +- .../PHPExcel/Worksheet/PageMargins.php | 2 +- .../PHPExcel/PHPExcel/Worksheet/PageSetup.php | 2 +- .../PHPExcel/Worksheet/Protection.php | 88 +- libraries/PHPExcel/PHPExcel/Worksheet/Row.php | 32 +- .../PHPExcel/Worksheet/RowDimension.php | 2 +- .../PHPExcel/Worksheet/RowIterator.php | 32 +- .../PHPExcel/PHPExcel/Worksheet/SheetView.php | 12 +- .../PHPExcel/PHPExcel/WorksheetIterator.php | 27 +- libraries/PHPExcel/PHPExcel/Writer/CSV.php | 23 +- .../PHPExcel/PHPExcel/Writer/Excel2007.php | 73 +- .../PHPExcel/Writer/Excel2007/Comments.php | 120 +-- .../Writer/Excel2007/ContentTypes.php | 34 +- .../PHPExcel/Writer/Excel2007/DocProps.php | 23 +- .../PHPExcel/Writer/Excel2007/Drawing.php | 67 +- .../PHPExcel/Writer/Excel2007/Rels.php | 26 +- .../PHPExcel/Writer/Excel2007/StringTable.php | 89 +- .../PHPExcel/Writer/Excel2007/Style.php | 82 +- .../PHPExcel/Writer/Excel2007/Theme.php | 617 ++++++----- .../PHPExcel/Writer/Excel2007/Workbook.php | 37 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 85 +- .../PHPExcel/Writer/Excel2007/WriterPart.php | 22 +- libraries/PHPExcel/PHPExcel/Writer/Excel5.php | 91 +- .../PHPExcel/Writer/Excel5/BIFFwriter.php | 10 +- .../PHPExcel/Writer/Excel5/Escher.php | 2 +- .../PHPExcel/PHPExcel/Writer/Excel5/Font.php | 17 +- .../PHPExcel/Writer/Excel5/Parser.php | 112 +- .../PHPExcel/Writer/Excel5/Workbook.php | 219 ++-- .../PHPExcel/Writer/Excel5/Worksheet.php | 660 ++++++------ .../PHPExcel/PHPExcel/Writer/Excel5/Xf.php | 41 +- libraries/PHPExcel/PHPExcel/Writer/HTML.php | 227 ++-- .../PHPExcel/PHPExcel/Writer/IWriter.php | 2 +- libraries/PHPExcel/PHPExcel/Writer/PDF.php | 240 ++++- .../PHPExcel/PHPExcel/Writer/Serialized.php | 33 +- 136 files changed, 7979 insertions(+), 5044 deletions(-) create mode 100644 libraries/PHPExcel/PHPExcel/Autoloader.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/APC.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/CacheBase.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/DiscISAM.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/ICache.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/Memcache.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/Memory.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemoryGZip.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemorySerialized.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/PHPTemp.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorage/Wincache.php create mode 100644 libraries/PHPExcel/PHPExcel/CachedObjectStorageFactory.php create mode 100644 libraries/PHPExcel/PHPExcel/Settings.php create mode 100644 libraries/PHPExcel/PHPExcel/Shared/CodePage.php create mode 100644 libraries/PHPExcel/PHPExcel/Shared/OLE/PPS.php create mode 100644 libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/File.php create mode 100644 libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php diff --git a/ChangeLog b/ChangeLog index df1988eff..ce0900b15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -81,6 +81,7 @@ $Id$ to Muhammad Adnan. + [doc] Incorporate synchronisation docs into main document. + [core] Include Content Security Policy HTTP headers. +- [core] Update library PHPExcel to version 1.7.3 3.3.4.0 (not yet released) - bug #2996161 [import] properly escape import value diff --git a/libraries/PHPExcel/PHPExcel.php b/libraries/PHPExcel/PHPExcel.php index a7ff765de..bd469e1ee 100644 --- a/libraries/PHPExcel/PHPExcel.php +++ b/libraries/PHPExcel/PHPExcel.php @@ -22,36 +22,22 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { define('PHPEXCEL_ROOT', dirname(__FILE__) . '/'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_DocumentProperties */ -require_once PHPEXCEL_ROOT . 'PHPExcel/DocumentProperties.php'; - -/** PHPExcel_DocumentSecurity */ -require_once PHPEXCEL_ROOT . 'PHPExcel/DocumentSecurity.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Shared_ZipStreamWrapper */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/ZipStreamWrapper.php'; - -/** PHPExcel_NamedRange */ -require_once PHPEXCEL_ROOT . 'PHPExcel/NamedRange.php'; - -/** PHPExcel_WorksheetIterator */ -require_once PHPEXCEL_ROOT . 'PHPExcel/WorksheetIterator.php'; - /** * PHPExcel @@ -146,6 +132,16 @@ class PHPExcel $this->addCellStyleXf(new PHPExcel_Style); } + + public function disconnectWorksheets() { + foreach($this->_workSheetCollection as $k => &$worksheet) { + $worksheet->disconnectCells(); + $this->_workSheetCollection[$k] = null; + } + unset($worksheet); + $this->_workSheetCollection = array(); + } + /** * Get properties * @@ -379,6 +375,23 @@ class PHPExcel return $this->getActiveSheet(); } + /** + * Set active sheet index by name + * + * @param string $pValue Sheet title + * @return PHPExcel_Worksheet + * @throws Exception + */ + public function setActiveSheetIndexByName($pValue = '') + { + if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) { + $this->setActiveSheetIndex($worksheet->getParent()->getIndex($worksheet)); + return $worksheet; + } + + throw new Exception('Workbook does not contain sheet:' . $pValue); + } + /** * Get sheet names * @@ -420,7 +433,8 @@ class PHPExcel $pSheet->rebindParent($this); // update the cellXfs - foreach ($pSheet->getCellCollection(false) as $cell) { + foreach ($pSheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); } @@ -443,7 +457,13 @@ class PHPExcel * @return PHPExcel */ public function addNamedRange(PHPExcel_NamedRange $namedRange) { - $this->_namedRanges[$namedRange->getWorksheet()->getTitle().'!'.$namedRange->getName()] = $namedRange; + if ($namedRange->getScope() == null) { + // global scope + $this->_namedRanges[$namedRange->getName()] = $namedRange; + } else { + // local scope + $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange; + } return true; } @@ -451,57 +471,42 @@ class PHPExcel * Get named range * * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope + * @return PHPExcel_NamedRange|null */ public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + $returnValue = null; + if ($namedRange != '' && !is_null($namedRange)) { - if (!is_null($pSheet)) { - $key = $pSheet->getTitle().'!'.$namedRange; - if (isset($this->_namedRanges[$key])) { - return $this->_namedRanges[$key]; - } + // first look for global defined name + if (isset($this->_namedRanges[$namedRange])) { + $returnValue = $this->_namedRanges[$namedRange]; } - $returnCount = 0; - foreach($this->_namedRanges as $_namedRange) { - if ($_namedRange->getName() == $namedRange) { - if ((!is_null($pSheet)) && ($_namedRange->getWorksheet()->getTitle() == $pSheet->getTitle())) { - return $_namedRange; - } else { - $returnCount++; - $returnValue = $_namedRange; - } - } - } - if ($returnCount == 1) { - return $returnValue; + + // then look for local defined name (has priority over global defined name if both names exist) + if (!is_null($pSheet) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]; } } - return null; + return $returnValue; } /** * Remove named range * * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet. Scope. Use null for global scope. * @return PHPExcel */ public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { - if ($namedRange != '' && !is_null($namedRange)) { - if (!is_null($pSheet)) { - $key = $pSheet->getTitle().'!'.$namedRange; - if (isset($this->_namedRanges[$key])) { - unset($this->_namedRanges[$key]); - } + if (is_null($pSheet)) { + if (isset($this->_namedRanges[$namedRange])) { + unset($this->_namedRanges[$namedRange]); } - foreach($this->_namedRanges as $_namedRange) { - if ($_namedRange->getName() == $namedRange) { - if ((!is_null($pSheet)) && ($_namedRange->getWorksheet()->getTitle() == $pSheet->getTitle())) { - $key = $pSheet->getTitle().'!'.$namedRange; - if (isset($this->_namedRanges[$key])) { - unset($this->_namedRanges[$key]); - } - } - } + } else { + if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]); } } return $this; @@ -622,7 +627,8 @@ class PHPExcel // then update cellXf indexes for cells foreach ($this->_workSheetCollection as $worksheet) { - foreach ($worksheet->getCellCollection(false) as $cell) { + foreach ($worksheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); $xfIndex = $cell->getXfIndex(); if ($xfIndex > $pIndex ) { // decrease xf index by 1 @@ -724,7 +730,8 @@ class PHPExcel foreach ($this->getWorksheetIterator() as $sheet) { // from cells - foreach ($sheet->getCellCollection(false) as $cell) { + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); ++$countReferencesCellXf[$cell->getXfIndex()]; } @@ -756,7 +763,7 @@ class PHPExcel // update the index for all cellXfs foreach ($this->_cellXfCollection as $i => $cellXf) { - echo $cellXf->setIndex($i); + $cellXf->setIndex($i); } // make sure there is always at least one cellXf (there should be) @@ -768,7 +775,8 @@ class PHPExcel foreach ($this->getWorksheetIterator() as $sheet) { // for all cells - foreach ($sheet->getCellCollection(false) as $cell) { + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); $cell->setXfIndex( $map[$cell->getXfIndex()] ); } diff --git a/libraries/PHPExcel/PHPExcel/Autoloader.php b/libraries/PHPExcel/PHPExcel/Autoloader.php new file mode 100644 index 000000000..ba667bbc2 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Autoloader.php @@ -0,0 +1,51 @@ +_currentObject->detach(); + + if (!apc_store($this->_cachePrefix.$this->_currentObjectID.'.cache',serialize($this->_currentObject),$this->_cacheTime)) { + $this->__destruct(); + throw new Exception('Failed to store cell in APC'); + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in apc + $success = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); + if ($success === false) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new Exception('Cell entry no longer exists in APC'); + } + return true; + } + return false; + } // function isDataSet() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (parent::isDataSet($pCoord)) { + $obj = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); + if ($obj === false) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new Exception('Cell entry no longer exists in APC'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws Exception + */ + public function deleteCacheData($pCoord) { + // Delete the entry from APC + apc_delete($this->_cachePrefix.$pCoord.'.cache'); + + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + + // Flush the APC cache + $this->__destruct(); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + + if (is_null($this->_cachePrefix)) { + if (function_exists('posix_getpid')) { + $baseUnique = posix_getpid(); + } else { + $baseUnique = mt_rand(); + } + $this->_cachePrefix = substr(md5(uniqid($baseUnique,true)),0,8).'.'; + $this->_cacheTime = $cacheTime; + + parent::__construct($parent); + } + } // function __construct() + + + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + apc_delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/CacheBase.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/CacheBase.php new file mode 100644 index 000000000..100df63e2 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/CacheBase.php @@ -0,0 +1,162 @@ +_parent = $parent; + } // function __construct() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return true; + } + // Check if the requested entry exists in the cache + return isset($this->_cellCache[$pCoord]); + } // function isDataSet() + + + /** + * Add or Update a cell in cache + * + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function updateCacheData(PHPExcel_Cell $cell) { + $pCoord = $cell->getCoordinate(); + + return $this->addCacheData($pCoord,$cell); + } // function updateCacheData() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws Exception + */ + public function deleteCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + $this->_currentObject->detach(); + $this->_currentObjectID = $this->_currentObject = null; + } + + if (isset($this->_cellCache[$pCoord])) { + $this->_cellCache[$pCoord]->detach(); + unset($this->_cellCache[$pCoord]); + } + } // function deleteCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + return array_keys($this->_cellCache); + } // function getCellList() + + + /** + * Sort the list of all cell addresses currently held in cache by column and row + * + * @return void + */ + public function sortCellList() { + $sortValues = array(); + foreach ($this->_cellCache as $coord => $value) { + preg_match('/^(\w+)(\d+)$/U',$coord,$matches); + list(,$colNum,$rowNum) = $matches; + + $key = str_pad($rowNum . str_pad($colNum,3,'@',STR_PAD_LEFT),12,'0',STR_PAD_LEFT); + + $sortValues[$key] = $coord; + } + ksort($sortValues); + + // Rebuild cellCollection from the sorted index + $newCellCollection = array(); + foreach ($sortValues as $coord) { + $newCellCollection[$coord] = $this->_cellCache[$coord]; + } + + $this->_cellCache = $newCellCollection; + } // function sortCellList() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/DiscISAM.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/DiscISAM.php new file mode 100644 index 000000000..b35f13831 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/DiscISAM.php @@ -0,0 +1,143 @@ +_currentObject->detach(); + + fseek($this->_fileHandle,0,SEEK_END); + $offset = ftell($this->_fileHandle); + fwrite($this->_fileHandle, serialize($this->_currentObject)); + $this->_cellCache[$this->_currentObjectID] = array('ptr' => $offset, + 'sz' => ftell($this->_fileHandle) - $offset + ); + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']); + $this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz'])); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + + // Close down the temporary cache file + $this->__destruct(); + } // function unsetWorksheetCells() + + + public function __construct(PHPExcel_Worksheet $parent) { + parent::__construct($parent); + if (is_null($this->_fileHandle)) { + if (function_exists('posix_getpid')) { + $baseUnique = posix_getpid(); + } else { + $baseUnique = mt_rand(); + } + $this->_fileName = sys_get_temp_dir().'/PHPExcel.'.uniqid($baseUnique,true).'.cache'; + $this->_fileHandle = fopen($this->_fileName,'a+'); + } + } // function __construct() + + + public function __destruct() { + if (!is_null($this->_fileHandle)) { + fclose($this->_fileHandle); + unlink($this->_fileName); + } + $this->_fileHandle = null; + } // function __destruct() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/ICache.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/ICache.php new file mode 100644 index 000000000..152167b3f --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/ICache.php @@ -0,0 +1,97 @@ +_currentObject->detach(); + + $obj = serialize($this->_currentObject); + if (!$this->_memcache->replace($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) { + if (!$this->_memcache->add($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) { + $this->__destruct(); + throw new Exception('Failed to store cell in Memcache'); + } + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in apc + $success = $this->_memcache->get($this->_cachePrefix.$pCoord.'.cache'); + if ($success === false) { + // Entry no longer exists in Memcache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new Exception('Cell entry no longer exists in Memcache'); + } + return true; + } + return false; + } // function isDataSet() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (parent::isDataSet($pCoord)) { + $obj = $this->_memcache->get($this->_cachePrefix.$pCoord.'.cache'); + if ($obj === false) { + // Entry no longer exists in Memcache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new Exception('Cell entry no longer exists in Memcache'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws Exception + */ + public function deleteCacheData($pCoord) { + // Delete the entry from Memcache + $this->_memcache->delete($this->_cachePrefix.$pCoord.'.cache'); + + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + + // Flush the Memcache cache + $this->__destruct(); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $memcacheServer = (isset($arguments['memcacheServer'])) ? $arguments['memcacheServer'] : 'localhost'; + $memcachePort = (isset($arguments['memcachePort'])) ? $arguments['memcachePort'] : 11211; + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + + if (is_null($this->_cachePrefix)) { + if (function_exists('posix_getpid')) { + $baseUnique = posix_getpid(); + } else { + $baseUnique = mt_rand(); + } + $this->_cachePrefix = substr(md5(uniqid($baseUnique,true)),0,8).'.'; + + // Set a new Memcache object and connect to the Memcache server + $this->_memcache = new Memcache(); + if (!$this->_memcache->connect($memcacheServer, $memcachePort)) { + throw new Exception('Could not connect to Memcache server at '.$memcacheServer.':'.$memcachePort); + } + $this->_cacheTime = $cacheTime; + + parent::__construct($parent); + } + } // function __construct() + + + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + $this->_memcache->delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() + +} + + +?> diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/Memory.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/Memory.php new file mode 100644 index 000000000..0472dac2c --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/Memory.php @@ -0,0 +1,85 @@ +_cellCache[$pCoord] = $cell; + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Return requested entry + return $this->_cellCache[$pCoord]; + } // function getCacheData() + + + public function unsetWorksheetCells() { + // Because cells are all stored as intact objects in memory, we need to detach each one from the parent + foreach($this->_cellCache as $k => &$cell) { + $cell->detach(); + $this->_cellCache[$k] = null; + } + unset($cell); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemoryGZip.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemoryGZip.php new file mode 100644 index 000000000..dfacdcc2d --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemoryGZip.php @@ -0,0 +1,107 @@ +_currentObject->detach(); + + $this->_cellCache[$this->_currentObjectID] = gzdeflate(serialize($this->_currentObject)); + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize(gzinflate($this->_cellCache[$pCoord])); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemorySerialized.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemorySerialized.php new file mode 100644 index 000000000..ae48ef55e --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/MemorySerialized.php @@ -0,0 +1,107 @@ +_currentObject->detach(); + + $this->_cellCache[$this->_currentObjectID] = serialize($this->_currentObject); + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($this->_cellCache[$pCoord]); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/PHPTemp.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/PHPTemp.php new file mode 100644 index 000000000..37676b1c2 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/PHPTemp.php @@ -0,0 +1,137 @@ +_currentObject->detach(); + + fseek($this->_fileHandle,0,SEEK_END); + $offset = ftell($this->_fileHandle); + fwrite($this->_fileHandle, serialize($this->_currentObject)); + $this->_cellCache[$this->_currentObjectID] = array('ptr' => $offset, + 'sz' => ftell($this->_fileHandle) - $offset + ); + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']); + $this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz'])); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + + // Close down the php://temp file + $this->__destruct(); + } // function unsetWorksheetCells() + + + public function __construct(PHPExcel_Worksheet $parent, $memoryCacheSize = '1MB') { + $memoryCacheSize = (isset($arguments['memoryCacheSize'])) ? $arguments['memoryCacheSize'] : '1MB'; + + parent::__construct($parent); + if (is_null($this->_fileHandle)) { + $this->_fileHandle = fopen('php://temp/maxmemory:'.$memoryCacheSize,'a+'); + } + } // function __construct() + + + public function __destruct() { + if (!is_null($this->_fileHandle)) { + fclose($this->_fileHandle); + } + $this->_fileHandle = null; + } // function __destruct() + +} diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorage/Wincache.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/Wincache.php new file mode 100644 index 000000000..9b30e78ea --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorage/Wincache.php @@ -0,0 +1,201 @@ +_currentObject->detach(); + + $obj = serialize($this->_currentObject); + if (wincache_ucache_exists($this->_cachePrefix.$this->_currentObjectID.'.cache')) { + wincache_ucache_set($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime); + } else { + wincache_ucache_add($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime); + } + + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + + return $cell; + } // function addCacheData() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in cache + $success = wincache_ucache_exists($this->_cachePrefix.$pCoord.'.cache'); + if ($success === false) { + // Entry no longer exists in Wincache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new Exception('Cell entry no longer exists in Wincache'); + } + return true; + } + return false; + } // function isDataSet() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + $obj = null; + if (parent::isDataSet($pCoord)) { + $success = false; + $obj = wincache_ucache_get($this->_cachePrefix.$pCoord.'.cache', $success); + if ($success === false) { + // Entry no longer exists in Wincache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new Exception('Cell entry no longer exists in Wincache'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach the parent worksheet + $this->_currentObject->attach($this->_parent); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws Exception + */ + public function deleteCacheData($pCoord) { + // Delete the entry from Wincache + wincache_ucache_delete($this->_cachePrefix.$pCoord.'.cache'); + + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() + + + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + + // Flush the Wincache cache + $this->__destruct(); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + + if (is_null($this->_cachePrefix)) { + if (function_exists('posix_getpid')) { + $baseUnique = posix_getpid(); + } else { + $baseUnique = mt_rand(); + } + $this->_cachePrefix = substr(md5(uniqid($baseUnique,true)),0,8).'.'; + $this->_cacheTime = $cacheTime; + + parent::__construct($parent); + } + } // function __construct() + + + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + wincache_ucache_delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() + +} + + +?> \ No newline at end of file diff --git a/libraries/PHPExcel/PHPExcel/CachedObjectStorageFactory.php b/libraries/PHPExcel/PHPExcel/CachedObjectStorageFactory.php new file mode 100644 index 000000000..d4c947976 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/CachedObjectStorageFactory.php @@ -0,0 +1,131 @@ + array( + ), + self::cache_in_memory_gzip => array( + ), + self::cache_in_memory_serialized => array( + ), + self::cache_to_phpTemp => array( 'memoryCacheSize' => '1MB' + ), + self::cache_to_discISAM => array( + ), + self::cache_to_apc => array( 'cacheTime' => 600 + ), + self::cache_to_memcache => array( 'memcacheServer' => 'localhost', + 'memcachePort' => 11211, + 'cacheTime' => 600 + ), + self::cache_to_wincache => array( 'cacheTime' => 600 + ) + ); + + + private static $_storageMethodParameters = array(); + + + public static function getCacheStorageMethod() { + if (!is_null(self::$_cacheStorageMethod)) { + return self::$_cacheStorageMethod; + } + return null; + } // function getCacheStorageMethod() + + + public static function getCacheStorageClass() { + if (!is_null(self::$_cacheStorageClass)) { + return self::$_cacheStorageClass; + } + return null; + } // function getCacheStorageClass() + + + public static function getCacheStorageMethods() { + return self::$_storageMethods; + } // function getCacheStorageMethods() + + + public static function initialize($method = self::cache_in_memory, $arguments = array()) { + if (!in_array($method,self::$_storageMethods)) { + return false; + } + + switch($method) { + case self::cache_to_apc : + if (!function_exists('apc_store')) { + return false; + } + if (apc_sma_info() === false) { + return false; + } + break; + case self::cache_to_memcache : + if (!function_exists('memcache_add')) { + return false; + } + break; + case self::cache_to_wincache : + if (!function_exists('wincache_ucache_add')) { + return false; + } + break; + } + + self::$_storageMethodParameters[$method] = self::$_storageMethodDefaultParameters[$method]; + foreach($arguments as $k => $v) { + if (isset(self::$_storageMethodParameters[$method][$k])) { + self::$_storageMethodParameters[$method][$k] = $v; + } + } + + if (is_null(self::$_cacheStorageMethod)) { + self::$_cacheStorageClass = 'PHPExcel_CachedObjectStorage_'.$method; + self::$_cacheStorageMethod = $method; + } + return true; + } // function initialize() + + + public static function getInstance(PHPExcel_Worksheet $parent) { + if (is_null(self::$_cacheStorageMethod)) { + self::initialize(); + } + + $instance = new self::$_cacheStorageClass($parent,self::$_storageMethodParameters[self::$_cacheStorageMethod]); + if (!is_null($instance)) { + return $instance; + } + + return false; + } // function getInstance() + +} \ No newline at end of file diff --git a/libraries/PHPExcel/PHPExcel/Calculation.php b/libraries/PHPExcel/PHPExcel/Calculation.php index 793734f91..7fe4d9997 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation.php +++ b/libraries/PHPExcel/PHPExcel/Calculation.php @@ -22,7 +22,7 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,17 +32,19 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } + /** Matrix */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; -/** PHPExcel_Calculation_Function */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Function.php'; - -/** PHPExcel_Calculation_Functions */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; - /** * PHPExcel_Calculation (Singleton) @@ -64,20 +66,21 @@ class PHPExcel_Calculation { // Function const CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\('; // Cell reference (cell or range of cells, with or without a sheet reference) - const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]+)\$?(\d+)'; + const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d+)'; // Named Range of cells const CALCULATION_REGEXP_NAMEDRANGE = '(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9]*)'; // Error const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?'; - /** constants */ + /** constants */ const RETURN_ARRAY_AS_ERROR = 'error'; const RETURN_ARRAY_AS_VALUE = 'value'; const RETURN_ARRAY_AS_ARRAY = 'array'; private static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE; + /** * Instance of this class * @@ -93,7 +96,7 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_calculationCache = array (); + private static $_calculationCache = array (); /** @@ -102,7 +105,7 @@ class PHPExcel_Calculation { * @access private * @var boolean */ - private $_calculationCacheEnabled = true; + private static $_calculationCacheEnabled = true; /** @@ -111,7 +114,7 @@ class PHPExcel_Calculation { * @access private * @var float */ - private $_calculationCacheExpirationTime = 2.5; + private static $_calculationCacheExpirationTime = 15; /** @@ -120,7 +123,7 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_operators = array('+', '-', '*', '/', '^', '&', '%', '~', '>', '<', '=', '>=', '<=', '<>', '|', ':'); + private static $_operators = array('+', '-', '*', '/', '^', '&', '%', '~', '>', '<', '=', '>=', '<=', '<>', '|', ':'); /** @@ -129,23 +132,80 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>', '|', ':'); + private static $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>', '|', ':'); + /** + * Flag to determine how formula errors should be handled + * If true, then a user error will be triggered + * If false, then an exception will be thrown + * + * @access public + * @var boolean + * + */ public $suppressFormulaErrors = false; + + /** + * Error message for any error that was raised/thrown by the calculation engine + * + * @access public + * @var string + * + */ public $formulaError = null; + + /** + * Flag to determine whether a debug log should be generated by the calculation engine + * If true, then a debug log will be generated + * If false, then a debug log will not be generated + * + * @access public + * @var boolean + * + */ public $writeDebugLog = false; + + /** + * An array of the nested cell references accessed by the calculation engine, used for the debug log + * + * @access private + * @var array of string + * + */ private $debugLogStack = array(); + + /** + * The debug log generated by the calculation engine + * + * @access public + * @var array of string + * + */ public $debugLog = array(); + private $_cyclicFormulaCount = 0; + private $_cyclicFormulaCell = ''; + public $cyclicFormulaCount = 0; + + + private static $_localeLanguage = 'en_us'; // US English (default locale) + private static $_validLocaleLanguages = array( 'en' // English (default language) + ); + private static $_localeArgumentSeparator = ','; + private static $_localeFunctions = array(); + private static $_localeBoolean = array( 'TRUE' => 'TRUE', + 'FALSE' => 'FALSE', + 'NULL' => 'NULL' + ); // Constant conversion from text name/value to actual (datatyped) value - private $_ExcelConstants = array('TRUE' => True, - 'FALSE' => False, - 'NULL' => Null - ); + private static $_ExcelConstants = array('TRUE' => True, + 'FALSE' => False, + 'NULL' => Null + ); // PHPExcel functions - private $_PHPExcelFunctions = array( // PHPExcel functions + private static $_PHPExcelFunctions = array( // PHPExcel functions 'ABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, 'functionCall' => 'abs', 'argumentCount' => '1' @@ -372,19 +432,19 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'COUPDAYBS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPDAYBS', 'argumentCount' => '3,4' ), 'COUPDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPDAYS', 'argumentCount' => '3,4' ), 'COUPDAYSNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPDAYSNC', 'argumentCount' => '3,4' ), 'COUPNCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPNCD', 'argumentCount' => '3,4' ), 'COUPNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -392,7 +452,7 @@ class PHPExcel_Calculation { 'argumentCount' => '3,4' ), 'COUPPCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPPCD', 'argumentCount' => '3,4' ), 'COVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -453,7 +513,7 @@ class PHPExcel_Calculation { ), 'DAVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::DAYOFMONTH', @@ -469,11 +529,11 @@ class PHPExcel_Calculation { ), 'DCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DCOUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, 'functionCall' => 'PHPExcel_Calculation_Functions::DDB', @@ -505,7 +565,7 @@ class PHPExcel_Calculation { ), 'DGET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, 'functionCall' => 'PHPExcel_Calculation_Functions::DISC', @@ -513,11 +573,11 @@ class PHPExcel_Calculation { ), 'DMAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DMIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, 'functionCall' => 'PHPExcel_Calculation_Functions::DOLLAR', @@ -533,19 +593,19 @@ class PHPExcel_Calculation { ), 'DPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DSTDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DSTDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', @@ -553,11 +613,11 @@ class PHPExcel_Calculation { ), 'DVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'DVARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'argumentCount' => '3' ), 'EDATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::EDATE', @@ -720,8 +780,9 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'HYPERLINK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '1,2' + 'functionCall' => 'PHPExcel_Calculation_Functions::HYPERLINK', + 'argumentCount' => '1,2', + 'passCellReference'=> true ), 'HYPGEOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, 'functionCall' => 'PHPExcel_Calculation_Functions::HYPGEOMDIST', @@ -1041,7 +1102,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1+' ), 'N' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::N', 'argumentCount' => '1' ), 'NA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -1175,7 +1236,7 @@ class PHPExcel_Calculation { 'argumentCount' => '4-6' ), 'PRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::PRICE', 'argumentCount' => '6,7' ), 'PRICEDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1484,7 +1545,7 @@ class PHPExcel_Calculation { 'argumentCount' => '4' ), 'TYPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::TYPE', 'argumentCount' => '1' ), 'UPPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, @@ -1579,7 +1640,7 @@ class PHPExcel_Calculation { // Internal functions used for special control purposes - private $_controlFunctions = array( + private static $_controlFunctions = array( 'MKMATRIX' => array('argumentCount' => '*', 'functionCall' => 'self::_mkMatrix' ) @@ -1588,6 +1649,17 @@ class PHPExcel_Calculation { + function __construct() { + $localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/'; + foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) { + $filename = substr($filename,strlen($localeFileDirectory)+1); + if ($filename != 'en') { + self::$_validLocaleLanguages[] = $filename; + } + } + } // function __construct() + + /** * Get an instance of this class * @@ -1650,7 +1722,7 @@ class PHPExcel_Calculation { * @return boolean */ public function getCalculationCacheEnabled() { - return $this->_calculationCacheEnabled; + return self::$_calculationCacheEnabled; } // function getCalculationCacheEnabled() @@ -1661,7 +1733,7 @@ class PHPExcel_Calculation { * @param boolean $pValue */ public function setCalculationCacheEnabled($pValue = true) { - $this->_calculationCacheEnabled = $pValue; + self::$_calculationCacheEnabled = $pValue; $this->clearCalculationCache(); } // function setCalculationCacheEnabled() @@ -1686,7 +1758,7 @@ class PHPExcel_Calculation { * Clear calculation cache */ public function clearCalculationCache() { - $this->_calculationCache = array(); + self::$_calculationCache = array(); } // function clearCalculationCache() @@ -1696,7 +1768,7 @@ class PHPExcel_Calculation { * @return float */ public function getCalculationCacheExpirationTime() { - return $this->_calculationCacheExpirationTime; + return self::$_calculationCacheExpirationTime; } // getCalculationCacheExpirationTime() @@ -1706,12 +1778,218 @@ class PHPExcel_Calculation { * @param float $pValue */ public function setCalculationCacheExpirationTime($pValue = 2.5) { - $this->_calculationCacheExpirationTime = $pValue; + self::$_calculationCacheExpirationTime = $pValue; } // function setCalculationCacheExpirationTime() + /** + * Get the currently defined locale code + * + * @return string + */ + public function getLocale() { + return self::$_localeLanguage; + } // function getLocale() + + + /** + * Set the locale code + * + * @return boolean + */ + public function setLocale($locale='en_us') { + // Identify our locale and language + $language = $locale = strtolower($locale); + if (strpos($locale,'_') !== false) { + list($language) = explode('_',$locale); + } + + // Test whether we have any language data for this language (any locale) + if (in_array($language,self::$_validLocaleLanguages)) { + // initialise language/locale settings + self::$_localeFunctions = array(); + self::$_localeArgumentSeparator = ','; + self::$_localeBoolean = array('TRUE' => 'TRUE', 'FALSE' => 'FALSE', 'NULL' => 'NULL'); + // Default is English, if user isn't requesting english, then read the necessary data from the locale files + if ($locale != 'en_us') { + // Search for a file with a list of function names for locale + $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.str_replace('_','/',$locale).'/functions'; + if (!file_exists($functionNamesFile)) { + // If there isn't a locale specific function file, look for a language specific function file + $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.$language.'/functions'; + if (!file_exists($functionNamesFile)) { + return false; + } + } + // Retrieve the list of locale or language specific function names + $localeFunctions = file($functionNamesFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($localeFunctions as $localeFunction) { + list($localeFunction) = explode('##',$localeFunction); // Strip out comments + if (strpos($localeFunction,'=') !== false) { + list($fName,$lfName) = explode('=',$localeFunction); + $fName = trim($fName); + $lfName = trim($lfName); + if ((isset(self::$_PHPExcelFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) { + self::$_localeFunctions[$fName] = $lfName; + } + } + } + // Default the TRUE and FALSE constants to the locale names of the TRUE() and FALSE() functions + if (isset(self::$_localeFunctions['TRUE'])) { self::$_localeBoolean['TRUE'] = self::$_localeFunctions['TRUE']; } + if (isset(self::$_localeFunctions['FALSE'])) { self::$_localeBoolean['FALSE'] = self::$_localeFunctions['FALSE']; } + + $configFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.str_replace('_','/',$locale).'/config'; + if (!file_exists($configFile)) { + $configFile = PHPEXCEL_ROOT . 'PHPExcel/locale/'.$language.'/config'; + } + if (file_exists($configFile)) { + $localeSettings = file($configFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($localeSettings as $localeSetting) { + list($localeSetting) = explode('##',$localeSetting); // Strip out comments + if (strpos($localeSetting,'=') !== false) { + list($settingName,$settingValue) = explode('=',$localeSetting); + $settingName = strtoupper(trim($settingName)); + switch ($settingName) { + case 'ARGUMENTSEPARATOR' : + self::$_localeArgumentSeparator = trim($settingValue); + break; + } + } + } + } + } + + self::$functionReplaceFromExcel = self::$functionReplaceToExcel = + self::$functionReplaceFromLocale = self::$functionReplaceToLocale = NULL; + self::$_localeLanguage = $locale; + return true; + } + return false; + } // function setLocale() + + + + public static function _translateSeparator($fromSeparator,$toSeparator,$formula,&$inBraces) { + $strlen = mb_strlen($formula); + for ($i = 0; $i < $strlen; ++$i) { + $chr = mb_substr($formula,$i,1); + switch ($chr) { + case '{' : $inBraces = True; + break; + case '}' : $inBraces = False; + break; + case $fromSeparator : + if (!$inBraces) { + $formula = mb_substr($formula,0,$i).$toSeparator.mb_substr($formula,$i+1); + } + } + } + return $formula; + } + + private static function _translateFormula($from,$to,$formula,$fromSeparator,$toSeparator) { + $inBraces = False; + // Convert any Excel function names to the required language + if (self::$_localeLanguage !== 'en_us') { + // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators + if (strpos($formula,'"') !== false) { + // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded + // the formula + $temp = explode('"',$formula); + foreach($temp as $i => &$value) { + // Only count/replace in alternate array entries + if (($i % 2) == 0) { + $value = preg_replace($from,$to,$value); + $value = self::_translateSeparator($fromSeparator,$toSeparator,$value,$inBraces); + } + } + unset($value); + // Then rebuild the formula string + $formula = implode('"',$temp); + } else { + // If there's no quoted strings, then we do a simple count/replace + $formula = preg_replace($from,$to,$formula); + $formula = self::_translateSeparator($fromSeparator,$toSeparator,$formula); + } + } + + return $formula; + } + + private static $functionReplaceFromExcel = NULL; + private static $functionReplaceToLocale = NULL; + + public function _translateFormulaToLocale($formula) { + if (is_null(self::$functionReplaceFromExcel)) { + self::$functionReplaceFromExcel = array(); + foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) { + self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelFunctionName).'([\s]*\()/Ui'; + } + foreach(array_keys(self::$_localeBoolean) as $excelBoolean) { + self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui'; + } + + } + + if (is_null(self::$functionReplaceToLocale)) { + self::$functionReplaceToLocale = array(); + foreach(array_values(self::$_localeFunctions) as $localeFunctionName) { + self::$functionReplaceToLocale[] = '$1'.trim($localeFunctionName).'$2'; + } + foreach(array_values(self::$_localeBoolean) as $localeBoolean) { + self::$functionReplaceToLocale[] = '$1'.trim($localeBoolean).'$2'; + } + } + + return self::_translateFormula(self::$functionReplaceFromExcel,self::$functionReplaceToLocale,$formula,',',self::$_localeArgumentSeparator); + } // function _translateFormulaToLocale() + + + private static $functionReplaceFromLocale = NULL; + private static $functionReplaceToExcel = NULL; + + public function _translateFormulaToEnglish($formula) { + if (is_null(self::$functionReplaceFromLocale)) { + self::$functionReplaceFromLocale = array(); + foreach(array_values(self::$_localeFunctions) as $localeFunctionName) { + self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($localeFunctionName).'([\s]*\()/Ui'; + } + foreach(array_values(self::$_localeBoolean) as $excelBoolean) { + self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui'; + } + } + + if (is_null(self::$functionReplaceToExcel)) { + self::$functionReplaceToExcel = array(); + foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) { + self::$functionReplaceToExcel[] = '$1'.trim($excelFunctionName).'$2'; + } + foreach(array_keys(self::$_localeBoolean) as $excelBoolean) { + self::$functionReplaceToExcel[] = '$1'.trim($excelBoolean).'$2'; + } + } + + return self::_translateFormula(self::$functionReplaceFromLocale,self::$functionReplaceToExcel,$formula,self::$_localeArgumentSeparator,','); + } // function _translateFormulaToEnglish() + + + public static function _localeFunc($function) { + if (self::$_localeLanguage !== 'en_us') { + $functionName = trim($function,'('); + if (isset(self::$_localeFunctions[$functionName])) { + $brace = ($functionName != $function); + $function = self::$_localeFunctions[$functionName]; + if ($brace) { $function .= '('; } + } + } + return $function; + } + + + + /** * Wrap string values in quotes * @@ -1767,7 +2045,11 @@ class PHPExcel_Calculation { * @throws Exception */ public function calculate(PHPExcel_Cell $pCell = null) { - return $this->calculateCellValue($pCell); + try { + return $this->calculateCellValue($pCell); + } catch (Exception $e) { + throw(new Exception($e->getMessage())); + } } // function calculate() @@ -1785,6 +2067,7 @@ class PHPExcel_Calculation { // Initialise the logging settings if requested $this->formulaError = null; $this->debugLog = $this->debugLogStack = array(); + $this->_cyclicFormulaCount = 1; $returnArrayAsType = self::$returnArrayAsType; self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; @@ -1799,7 +2082,11 @@ class PHPExcel_Calculation { self::$returnArrayAsType = $returnArrayAsType; } // Execute the calculation for the cell formula - $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); + try { + $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); + } catch (Exception $e) { + throw(new Exception($e->getMessage())); + } if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { $testResult = PHPExcel_Calculation_Functions::flattenArray($result); @@ -1809,10 +2096,12 @@ class PHPExcel_Calculation { // If there's only a single cell in the array, then we allow it if (count($testResult) != 1) { // If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it - $r = array_shift(array_keys($result)); + $r = array_keys($result); + $r = array_shift($r); if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); } if (is_array($result[$r])) { - $c = array_shift(array_keys($result[$r])); + $c = array_keys($result[$r]); + $c = array_shift($c); if (!is_numeric($c)) { return PHPExcel_Calculation_Functions::VALUE(); } @@ -1841,7 +2130,7 @@ class PHPExcel_Calculation { // Basic validation that this is indeed a formula // We return an empty array if not $formula = trim($formula); - if ($formula{0} != '=') return array(); + if ((strlen($formula) == 0) || ($formula{0} != '=')) return array(); $formula = trim(substr($formula,1)); $formulaLength = strlen($formula); if ($formulaLength < 1) return array(); @@ -1866,11 +2155,16 @@ class PHPExcel_Calculation { // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache $resetCache = $this->getCalculationCacheEnabled(); - $this->_calculationCacheEnabled = false; + self::$_calculationCacheEnabled = false; // Execute the calculation - $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); + try { + $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); + } catch (Exception $e) { + throw(new Exception($e->getMessage())); + } + // Reset calculation cacheing to its previous state - $this->_calculationCacheEnabled = $resetCache; + self::$_calculationCacheEnabled = $resetCache; return $result; } // function calculateFormula() @@ -1899,47 +2193,69 @@ class PHPExcel_Calculation { $wsTitle = 'Wrk'; if (!is_null($pCell)) { - $wsTitle = urlencode($pCell->getParent()->getTitle()); + $pCellParent = $pCell->getParent(); + if (!is_null($pCellParent)) { + $wsTitle = $pCellParent->getTitle(); + } } // Is calculation cacheing enabled? if (!is_null($cellID)) { - if ($this->_calculationCacheEnabled) { + if (self::$_calculationCacheEnabled) { // Is the value present in calculation cache? // echo 'Testing cache value
'; - if (isset($this->_calculationCache[$wsTitle][$cellID])) { + if (isset(self::$_calculationCache[$wsTitle][$cellID])) { // echo 'Value is in cache
'; $this->_writeDebug('Testing cache value for cell '.$cellID); // Is cache still valid? - if ((time() + microtime(true)) - $this->_calculationCache[$wsTitle][$cellID]['time'] < $this->_calculationCacheExpirationTime) { + if ((time() + microtime(true)) - self::$_calculationCache[$wsTitle][$cellID]['time'] < self::$_calculationCacheExpirationTime) { // echo 'Cache time is still valid
'; $this->_writeDebug('Retrieving value for '.$cellID.' from cache'); // Return the cached result - $returnValue = $this->_calculationCache[$wsTitle][$cellID]['data']; + $returnValue = self::$_calculationCache[$wsTitle][$cellID]['data']; // echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
'; if (is_array($returnValue)) { - return array_shift(PHPExcel_Calculation_Functions::flattenArray($returnValue)); + $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue); + return array_shift($returnValue); } return $returnValue; } else { // echo 'Cache has expired
'; $this->_writeDebug('Cache value for '.$cellID.' has expired'); // Clear the cache if it's no longer valid - unset($this->_calculationCache[$wsTitle][$cellID]); + unset(self::$_calculationCache[$wsTitle][$cellID]); } } } } - $this->debugLogStack[] = $cellID; + if ((in_array($wsTitle.'!'.$cellID,$this->debugLogStack)) && ($wsTitle != 'Wrk')) { + if ($this->cyclicFormulaCount <= 0) { + return $this->_raiseFormulaError('Cyclic Reference in Formula'); + } elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) && + ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID)) { + return $cellValue; + } elseif ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID) { + $this->_cyclicFormulaCount++; + if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) { + return $cellValue; + } + } elseif ($this->_cyclicFormulaCell == '') { + $this->_cyclicFormulaCell = $wsTitle.'!'.$cellID; + if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) { + return $cellValue; + } + } + } + $this->debugLogStack[] = $wsTitle.'!'.$cellID; // Parse the formula onto the token stack and calculate the value $cellValue = $this->_processTokenStack($this->_parseFormula($formula), $cellID, $pCell); array_pop($this->debugLogStack); // Save to calculation cache if (!is_null($cellID)) { - if ($this->_calculationCacheEnabled) { - $this->_calculationCache[$wsTitle][$cellID]['time'] = (time() + microtime(true)); - $this->_calculationCache[$wsTitle][$cellID]['data'] = $cellValue; + if (self::$_calculationCacheEnabled) { + self::$_calculationCache[$wsTitle][$cellID]['time'] = (time() + microtime(true)); + self::$_calculationCache[$wsTitle][$cellID]['data'] = $cellValue; } } @@ -2003,7 +2319,11 @@ class PHPExcel_Calculation { if ($colCount > $matrixColumns) { $matrixColumns = $colCount; } - $matrix[$rowKey] = array_values($rowValue); + if (!is_array($rowValue)) { + $matrix[$rowKey] = array($rowValue); + } else { + $matrix[$rowKey] = array_values($rowValue); + } } $matrix = array_values($matrix); return array($matrixRows,$matrixColumns); @@ -2105,6 +2425,11 @@ class PHPExcel_Calculation { * @return mixed */ private static function _showValue($value) { + $testArray = PHPExcel_Calculation_Functions::flattenArray($value); + if (count($testArray) == 1) { + $value = array_pop($testArray); + } + if (is_array($value)) { $returnMatrix = array(); $pad = $rpad = ', '; @@ -2118,7 +2443,7 @@ class PHPExcel_Calculation { } return '{ '.implode($rpad,$returnMatrix).' }'; } elseif(is_bool($value)) { - return ($value) ? 'TRUE' : 'FALSE'; + return ($value) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE']; } return $value; @@ -2132,6 +2457,11 @@ class PHPExcel_Calculation { * @return mixed */ private static function _showTypeDetails($value) { + $testArray = PHPExcel_Calculation_Functions::flattenArray($value); + if (count($testArray) == 1) { + $value = array_pop($testArray); + } + switch (gettype($value)) { case 'double' : case 'float' : @@ -2297,11 +2627,11 @@ class PHPExcel_Calculation { } elseif (($opCharacter == '~') && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, because it's legal return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression - } elseif ((in_array($opCharacter, $this->_operators) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? + } elseif ((in_array($opCharacter, self::$_operators) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? // echo 'Element with value '.$opCharacter.' is an Operator
'; while($stack->count() > 0 && ($o2 = $stack->last()) && - in_array($o2['value'], $this->_operators) && + in_array($o2['value'], self::$_operators) && @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } @@ -2331,14 +2661,14 @@ class PHPExcel_Calculation { // } $output[] = $d; // Dump the argument count on the output $output[] = $stack->pop(); // Pop the function and push onto the output - if (array_key_exists($functionName, $this->_controlFunctions)) { + if (array_key_exists($functionName, self::$_controlFunctions)) { // echo 'Built-in function '.$functionName.'
'; - $expectedArgumentCount = $this->_controlFunctions[$functionName]['argumentCount']; - $functionCall = $this->_controlFunctions[$functionName]['functionCall']; - } elseif (array_key_exists($functionName, $this->_PHPExcelFunctions)) { + $expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount']; + $functionCall = self::$_controlFunctions[$functionName]['functionCall']; + } elseif (array_key_exists($functionName, self::$_PHPExcelFunctions)) { // echo 'PHPExcel function '.$functionName.'
'; - $expectedArgumentCount = $this->_PHPExcelFunctions[$functionName]['argumentCount']; - $functionCall = $this->_PHPExcelFunctions[$functionName]['functionCall']; + $expectedArgumentCount = self::$_PHPExcelFunctions[$functionName]['argumentCount']; + $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall']; } else { // did we somehow push a non-function on the stack? this should never happen return $this->_raiseFormulaError("Formula Error: Internal error, non-function on stack"); } @@ -2389,21 +2719,21 @@ class PHPExcel_Calculation { } ++$index; - } elseif ($opCharacter == ',') { // Is this the comma separator for function arguments? + } elseif ($opCharacter == ',') { // Is this the separator for function arguments? // echo 'Element is a Function argument separator
'; while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( - if (is_null($o2)) return $this->_raiseFormulaError("Formula Error: Unexpected ','"); + if (is_null($o2)) return $this->_raiseFormulaError("Formula Error: Unexpected ,"); else $output[] = $o2; // pop the argument expression stuff and push onto the output } // If we've a comma when we're expecting an operand, then what we actually have is a null operand; // so push a null onto the stack if (($expectingOperand) || (!$expectingOperator)) { - $output[] = array('type' => 'NULL Value', 'value' => $this->_ExcelConstants['NULL'], 'reference' => NULL); + $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL); } // make sure there was a function $d = $stack->last(2); if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) - return $this->_raiseFormulaError("Formula Error: Unexpected ','"); + return $this->_raiseFormulaError("Formula Error: Unexpected ,"); $d = $stack->pop(); $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again @@ -2426,14 +2756,14 @@ class PHPExcel_Calculation { if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) { $val = preg_replace('/\s/','',$val); // echo 'Element '.$val.' is a Function
'; - if (array_key_exists(strtoupper($matches[1]), $this->_PHPExcelFunctions) || array_key_exists(strtoupper($matches[1]), $this->_controlFunctions)) { // it's a func + if (array_key_exists(strtoupper($matches[1]), self::$_PHPExcelFunctions) || array_key_exists(strtoupper($matches[1]), self::$_controlFunctions)) { // it's a func $stack->push('Function', strtoupper($val)); $ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch); if ($ax) { - $stack->push('Operand Count for Function '.strtoupper($val).')', 0); + $stack->push('Operand Count for Function '.self::_localeFunc(strtoupper($val)).')', 0); $expectingOperator = true; } else { - $stack->push('Operand Count for Function '.strtoupper($val).')', 1); + $stack->push('Operand Count for Function '.self::_localeFunc(strtoupper($val)).')', 1); $expectingOperator = false; } $stack->push('Brace', '('); @@ -2450,9 +2780,11 @@ class PHPExcel_Calculation { // $expectingOperator = false; } else { // it's a variable, constant, string, number or boolean // echo 'Element is a Variable, Constant, String, Number or Boolean
'; + $localeConstant = false; if ($opCharacter == '"') { // echo 'Element is a String
'; - $val = str_replace('""','"',$val); + // UnEscape any quotes within the string + $val = self::_wrapResult(str_replace('""','"',self::_unwrapResult($val))); } elseif (is_numeric($val)) { // echo 'Element is a Number
'; if ((strpos($val,'.') !== False) || (stripos($val,'e') !== False) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) { @@ -2462,24 +2794,29 @@ class PHPExcel_Calculation { // echo 'Casting '.$val.' to integer
'; $val = (integer) $val; } - } elseif (array_key_exists(trim(strtoupper($val)), $this->_ExcelConstants)) { + } elseif (array_key_exists(trim(strtoupper($val)), self::$_ExcelConstants)) { $excelConstant = trim(strtoupper($val)); // echo 'Element '.$excelConstant.' is an Excel Constant
'; - $val = $this->_ExcelConstants[$excelConstant]; + $val = self::$_ExcelConstants[$excelConstant]; + } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== false) { +// echo 'Element '.$localeConstant.' is an Excel Constant
'; + $val = self::$_ExcelConstants[$localeConstant]; } - $output[] = array('type' => 'Value', 'value' => $val, 'reference' => NULL); + $details = array('type' => 'Value', 'value' => $val, 'reference' => NULL); + if ($localeConstant) { $details['localeValue'] = $localeConstant; } + $output[] = $details; } $index += $length; } elseif ($opCharacter == ')') { // miscellaneous error checking if ($expectingOperand) { - $output[] = array('type' => 'Null Value', 'value' => $this->_ExcelConstants['NULL'], 'reference' => NULL); + $output[] = array('type' => 'Null Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL); $expectingOperand = false; $expectingOperator = True; } else { return $this->_raiseFormulaError("Formula Error: Unexpected ')'"); } - } elseif (in_array($opCharacter, $this->_operators) && !$expectingOperator) { + } elseif (in_array($opCharacter, self::$_operators) && !$expectingOperator) { return $this->_raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'"); } else { // I don't even want to know what you did to get here return $this->_raiseFormulaError("Formula Error: An unexpected error occured"); @@ -2488,7 +2825,7 @@ class PHPExcel_Calculation { if ($index == strlen($formula)) { // Did we end with an operator?. // Only valid for the % unary operator - if ((in_array($opCharacter, $this->_operators)) && ($opCharacter != '%')) { + if ((in_array($opCharacter, self::$_operators)) && ($opCharacter != '%')) { return $this->_raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands"); } else { break; @@ -2510,7 +2847,7 @@ class PHPExcel_Calculation { // echo 'Element is an Intersect Operator
'; while($stack->count() > 0 && ($o2 = $stack->last()) && - in_array($o2['value'], $this->_operators) && + in_array($o2['value'], self::$_operators) && @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } @@ -2529,9 +2866,12 @@ class PHPExcel_Calculation { // evaluate postfix notation - private function _processTokenStack($tokens, $cellID=null, PHPExcel_Cell $pCell = null) { + private function _processTokenStack($tokens, $cellID = null, PHPExcel_Cell $pCell = null) { if ($tokens == false) return false; + // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet), + // so we store the parent worksheet so that we can re-attach it when necessary + $pCellParent = (!is_null($pCell)) ? $pCell->getParent() : null; $stack = new PHPExcel_Token_Stack; // Loop through each token in turn @@ -2541,7 +2881,7 @@ class PHPExcel_Calculation { $token = $tokenData['value']; // echo 'Token is '.$token.'
'; // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack - if (in_array($token, $this->_binaryOperators, true)) { + if (in_array($token, self::$_binaryOperators, true)) { // echo 'Token is a binary operator
'; // We must have two operands, error if we don't if (is_null($operand2Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); @@ -2571,7 +2911,7 @@ class PHPExcel_Calculation { if (strpos($operand1Data['reference'],'!') !== false) { list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']); } else { - $sheet1 = $pCell->getParent()->getTitle(); + $sheet1 = (!is_null($pCellParent)) ? $pCellParent->getTitle() : ''; } if (strpos($operand2Data['reference'],'!') !== false) { list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); @@ -2606,7 +2946,11 @@ class PHPExcel_Calculation { $oRow[] = $oCR[1]; } $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); - $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($sheet1), false); + if (!is_null($pCellParent)) { + $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($sheet1), false); + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } $stack->push('Cell Reference',$cellValue,$cellRef); } else { $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL); @@ -2633,10 +2977,10 @@ class PHPExcel_Calculation { // (converting the other operand to a matrix if need be); then perform the required // matrix operation if (is_bool($operand1)) { - $operand1 = ($operand1) ? 'TRUE' : 'FALSE'; + $operand1 = ($operand1) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE']; } if (is_bool($operand2)) { - $operand2 = ($operand2) ? 'TRUE' : 'FALSE'; + $operand2 = ($operand2) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE']; } if ((is_array($operand1)) || (is_array($operand2))) { // Ensure that both operands are arrays/matrices @@ -2717,12 +3061,21 @@ class PHPExcel_Calculation { $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]); - $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false); + if (!is_null($pCellParent)) { + $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false); + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } $this->_writeDebug('Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); + $cellRef = $matches[2].'!'.$cellRef; } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in current worksheet'); - $cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false); + if (!is_null($pCellParent)) { + $cellValue = $this->extractCellRange($cellRef, $pCellParent, false); + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } $this->_writeDebug('Evaluation Result for cells '.$cellRef.' is '.self::_showTypeDetails($cellValue)); } } @@ -2737,17 +3090,22 @@ class PHPExcel_Calculation { $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; $this->_writeDebug('Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]); - if ($pCell->getParent()->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) { - $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false); + if (!is_null($pCellParent)) { + if ($pCellParent->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false); + } else { + $cellValue = PHPExcel_Calculation_Functions::REF(); + } } else { - $cellValue = PHPExcel_Calculation_Functions::REF(); + return $this->_raiseFormulaError('Unable to access Cell Reference'); } $this->_writeDebug('Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); + $cellRef = $matches[2].'!'.$cellRef; } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; $this->_writeDebug('Evaluating Cell '.$cellRef.' in current worksheet'); - if ($pCell->getParent()->cellExists($cellRef)) { - $cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false); + if ($pCellParent->cellExists($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $pCellParent, false); } else { $cellValue = NULL; } @@ -2764,17 +3122,17 @@ class PHPExcel_Calculation { $argCount = $stack->pop(); $argCount = $argCount['value']; if ($functionName != 'MKMATRIX') { - $this->_writeDebug('Evaluating Function '.$functionName.'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); + $this->_writeDebug('Evaluating Function '.self::_localeFunc($functionName).'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); } - if ((array_key_exists($functionName, $this->_PHPExcelFunctions)) || (array_key_exists($functionName, $this->_controlFunctions))) { // function - if (array_key_exists($functionName, $this->_PHPExcelFunctions)) { - $functionCall = $this->_PHPExcelFunctions[$functionName]['functionCall']; - $passByReference = isset($this->_PHPExcelFunctions[$functionName]['passByReference']); - $passCellReference = isset($this->_PHPExcelFunctions[$functionName]['passCellReference']); - } elseif (array_key_exists($functionName, $this->_controlFunctions)) { - $functionCall = $this->_controlFunctions[$functionName]['functionCall']; - $passByReference = isset($this->_controlFunctions[$functionName]['passByReference']); - $passCellReference = isset($this->_controlFunctions[$functionName]['passCellReference']); + if ((array_key_exists($functionName, self::$_PHPExcelFunctions)) || (array_key_exists($functionName, self::$_controlFunctions))) { // function + if (array_key_exists($functionName, self::$_PHPExcelFunctions)) { + $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall']; + $passByReference = isset(self::$_PHPExcelFunctions[$functionName]['passByReference']); + $passCellReference = isset(self::$_PHPExcelFunctions[$functionName]['passCellReference']); + } elseif (array_key_exists($functionName, self::$_controlFunctions)) { + $functionCall = self::$_controlFunctions[$functionName]['functionCall']; + $passByReference = isset(self::$_controlFunctions[$functionName]['passByReference']); + $passCellReference = isset(self::$_controlFunctions[$functionName]['passCellReference']); } // get the arguments for this function // echo 'Function '.$functionName.' expects '.$argCount.' arguments
'; @@ -2783,8 +3141,8 @@ class PHPExcel_Calculation { $arg = $stack->pop(); $a = $argCount - $i - 1; if (($passByReference) && - (isset($this->_PHPExcelFunctions[$functionName]['passByReference'][$a])) && - ($this->_PHPExcelFunctions[$functionName]['passByReference'][$a])) { + (isset(self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) && + (self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) { if (is_null($arg['reference'])) { $args[] = $cellID; if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($cellID); } @@ -2808,7 +3166,7 @@ class PHPExcel_Calculation { // echo '
'; if ($functionName != 'MKMATRIX') { krsort($argArrayVals); - $this->_writeDebug('Evaluating '. $functionName.'( '.implode(', ',$argArrayVals).' )'); + $this->_writeDebug('Evaluating '. self::_localeFunc($functionName).'( '.implode(self::$_localeArgumentSeparator.' ',$argArrayVals).' )'); } // Process each argument in turn, building the return value as an array // if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) { @@ -2819,16 +3177,16 @@ class PHPExcel_Calculation { // foreach($operand1 as $args) { // if (is_array($args)) { // foreach($args as $arg) { -// $this->_writeDebug('Evaluating '. $functionName.'( '.self::_showValue($arg).' )'); +// $this->_writeDebug('Evaluating '.self::_localeFunc($functionName).'( '.self::_showValue($arg).' )'); // $r = call_user_func_array($functionCall,$arg); -// $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($r)); +// $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.self::_showTypeDetails($r)); // $result[$row][] = $r; // } // ++$row; // } else { -// $this->_writeDebug('Evaluating '. $functionName.'( '.self::_showValue($args).' )'); +// $this->_writeDebug('Evaluating '.self::_localeFunc($functionName).'( '.self::_showValue($args).' )'); // $r = call_user_func_array($functionCall,$args); -// $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($r)); +// $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.self::_showTypeDetails($r)); // $result[] = $r; // } // } @@ -2848,18 +3206,18 @@ class PHPExcel_Calculation { } // } if ($functionName != 'MKMATRIX') { - $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.self::_showTypeDetails($result)); } $stack->push('Value',self::_wrapResult($result)); } } else { // if the token is a number, boolean, string or an Excel error, push it onto the stack - if (array_key_exists(strtoupper($token), $this->_ExcelConstants)) { + if (array_key_exists(strtoupper($token), self::$_ExcelConstants)) { $excelConstant = strtoupper($token); // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; - $stack->push('Constant Value',$this->_ExcelConstants[$excelConstant]); - $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails($this->_ExcelConstants[$excelConstant])); + $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]); + $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails(self::$_ExcelConstants[$excelConstant])); } elseif ((is_numeric($token)) || (is_bool($token)) || (is_null($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { // echo 'Token is a number, boolean, string, null or an Excel error
'; $stack->push('Value',$token); @@ -2869,7 +3227,7 @@ class PHPExcel_Calculation { $namedRange = $matches[6]; // echo 'Named Range is '.$namedRange.'
'; $this->_writeDebug('Evaluating Named Range '.$namedRange); - $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCell->getParent() : null), false); + $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCellParent : null), false); $this->_writeDebug('Evaluation Result for named range '.$namedRange.' is '.self::_showTypeDetails($cellValue)); $stack->push('Named Range',$cellValue,$namedRange); } else { @@ -3061,9 +3419,8 @@ class PHPExcel_Calculation { // trigger an error, but nicely, if need be - private function _raiseFormulaError($errorMessage) { + protected function _raiseFormulaError($errorMessage) { $this->formulaError = $errorMessage; - echo '_raiseFormulaError message is '.$errorMessage.'
'; if (!$this->suppressFormulaErrors) throw new Exception($errorMessage); trigger_error($errorMessage, E_USER_ERROR); } // function _raiseFormulaError() @@ -3152,16 +3509,17 @@ class PHPExcel_Calculation { // Named range? $namedRange = PHPExcel_NamedRange::resolveRange($pRange, $pSheet); if (!is_null($namedRange)) { -// echo 'Named Range '.$pRange.' ('; + $pSheet = $namedRange->getWorksheet(); +//// echo 'Named Range '.$pRange.' ('; $pRange = $namedRange->getRange(); -// echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'
'; - if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) { - if (!$namedRange->getLocalOnly()) { - $pSheet = $namedRange->getWorksheet(); - } else { - return $returnValue; - } - } +//// echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'
'; +// if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) { +// if (!$namedRange->getLocalOnly()) { +// $pSheet = $namedRange->getWorksheet(); +// } else { +// return $returnValue; +// } +// } } else { return PHPExcel_Calculation_Functions::REF(); } @@ -3205,8 +3563,8 @@ class PHPExcel_Calculation { */ public function isImplemented($pFunction = '') { $pFunction = strtoupper ($pFunction); - if (isset($this->_PHPExcelFunctions[$pFunction])) { - return ($this->_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY'); + if (isset(self::$_PHPExcelFunctions[$pFunction])) { + return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY'); } else { return false; } @@ -3222,7 +3580,7 @@ class PHPExcel_Calculation { // Return value $returnValue = array(); // Loop functions - foreach($this->_PHPExcelFunctions as $functionName => $function) { + foreach(self::$_PHPExcelFunctions as $functionName => $function) { if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') { $returnValue[$functionName] = new PHPExcel_Calculation_Function($function['category'], $functionName, @@ -3242,7 +3600,7 @@ class PHPExcel_Calculation { * @return array */ public function listFunctionNames() { - return array_keys($this->_PHPExcelFunctions); + return array_keys(self::$_PHPExcelFunctions); } // function listFunctionNames() } // class PHPExcel_Calculation @@ -3267,6 +3625,12 @@ class PHPExcel_Token_Stack { 'value' => $value, 'reference' => $reference ); + if ($type == 'Function') { + $localeFunction = PHPExcel_Calculation::_localeFunc($value); + if ($localeFunction != $value) { + $this->_stack[($this->_count - 1)]['localeValue'] = $localeFunction; + } + } } // function push() diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Exception.php b/libraries/PHPExcel/PHPExcel/Calculation/Exception.php index 84cf09d79..a113e9ec6 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Exception.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Exception.php @@ -22,7 +22,7 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php b/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php index 48475df5c..81f3fbac3 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php @@ -22,20 +22,9 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Calculation_Exception */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Exception.php'; - /** * PHPExcel_Calculation_ExceptionHandler * @@ -43,14 +32,14 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Exception.php'; * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Calculation_ExceptionHandler { +class PHPExcel_Calculation_ExceptionHandler { /** * Register errorhandler */ public function __construct() { - set_error_handler(array('PHPExcel_Calculation_Exception', 'errorHandlerCallback'), E_ALL); + set_error_handler(array('PHPExcel_Calculation_Exception', 'errorHandlerCallback'), E_ALL); } - + /** * Unregister errorhandler */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php b/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php index d6bf785ad..5565217d3 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php @@ -22,7 +22,7 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -49,17 +49,6 @@ PARTLY BASED ON: http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Calculation_FormulaToken */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaToken.php'; - /** * PHPExcel_Calculation_FormulaParser * diff --git a/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php b/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php index 091e69d0b..6f55208f2 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php @@ -22,7 +22,7 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Function.php b/libraries/PHPExcel/PHPExcel/Calculation/Function.php index 6ea8aea10..7da6732fe 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Function.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Function.php @@ -22,7 +22,7 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Functions.php b/libraries/PHPExcel/PHPExcel/Calculation/Functions.php index 2ba67fd77..7f1cc18e6 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Functions.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Functions.php @@ -22,10 +22,26 @@ * @package PHPExcel_Calculation * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } +} + + /** EPS */ define('EPS', 2.22e-16); @@ -63,29 +79,6 @@ if ($savedPrecision < 16) { } -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Calculation */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Style_NumberFormat */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - /** Matrix */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php'; @@ -122,7 +115,7 @@ class PHPExcel_Calculation_Functions { * Data Type to use when returning date values * * @access private - * @var integer + * @var string */ private static $ReturnDateType = self::RETURNDATE_EXCEL; @@ -236,8 +229,14 @@ class PHPExcel_Calculation_Functions { /** * NA * + * Excel Function: + * =NA() + * + * Returns the error value #N/A + * #N/A is the error value that means "no value is available." + * * @access public - * @category Error Returns + * @category Logical Functions * @return string #N/A! */ public static function NA() { @@ -248,6 +247,8 @@ class PHPExcel_Calculation_Functions { /** * NAN * + * Returns the error value #NUM! + * * @access public * @category Error Returns * @return string #NUM! @@ -260,9 +261,11 @@ class PHPExcel_Calculation_Functions { /** * NAME * + * Returns the error value #NAME? + * * @access public * @category Error Returns - * @return string #NAME! + * @return string #NAME? */ public static function NAME() { return self::$_errorCodes['name']; @@ -272,6 +275,8 @@ class PHPExcel_Calculation_Functions { /** * REF * + * Returns the error value #REF! + * * @access public * @category Error Returns * @return string #REF! @@ -284,6 +289,8 @@ class PHPExcel_Calculation_Functions { /** * VALUE * + * Returns the error value #VALUE! + * * @access public * @category Error Returns * @return string #VALUE! @@ -552,6 +559,39 @@ class PHPExcel_Calculation_Functions { } // function STATEMENT_IFERROR() + /** + * HYPERLINK + * + * Excel Function: + * =HYPERLINK(linkURL,displayName) + * + * @access public + * @category Logical Functions + * @param string $linkURL Value to check, is also the value returned when no error + * @param string $displayName Value to return when testValue is an error condition + * @return mixed The value of errorpart or testValue determined by error condition + */ + public static function HYPERLINK($linkURL = '', $displayName = null, PHPExcel_Cell $pCell = null) { + $args = func_get_args(); + $pCell = array_pop($args); + + $linkURL = (is_null($linkURL)) ? '' : self::flattenSingleValue($linkURL); + $displayName = (is_null($displayName)) ? '' : self::flattenSingleValue($displayName); + + if ((!is_object($pCell)) || (trim($linkURL) == '')) { + return self::$_errorCodes['reference']; + } + + if ((is_object($displayName)) || trim($displayName) == '') { + $displayName = $linkURL; + } + + $pCell->getHyperlink()->setUrl($linkURL); + + return $displayName; + } // function HYPERLINK() + + /** * ATAN2 * @@ -826,6 +866,46 @@ class PHPExcel_Calculation_Functions { } // function MINA() + /** + * MINIF + * + * Returns the minimum value within a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * MINIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be checked. + * @return float + */ + public static function MINIF($aArgs,$condition,$sumArgs = array()) { + // Return value + $returnValue = null; + + $aArgs = self::flattenArray($aArgs); + $sumArgs = self::flattenArray($sumArgs); + if (count($sumArgs) == 0) { + $sumArgs = $aArgs; + } + $condition = self::_ifCondition($condition); + // Loop through arguments + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + if ((is_null($returnValue)) || ($arg < $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + return $returnValue; + } // function MINIF() + + /** * SMALL * @@ -945,6 +1025,59 @@ class PHPExcel_Calculation_Functions { } // function MAXA() + private static function _ifCondition($condition) { + $condition = self::flattenSingleValue($condition); + if (!in_array($condition{0},array('>', '<', '='))) { + if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } + return '='.$condition; + } else { + preg_match('/([<>=]+)(.*)/',$condition,$matches); + list(,$operator,$operand) = $matches; + if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + return $operator.$operand; + } + } // function _ifCondition() + + /** + * MAXIF + * + * Counts the maximum value within a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * MAXIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be checked. + * @return float + */ + public static function MAXIF($aArgs,$condition,$sumArgs = array()) { + // Return value + $returnValue = null; + + $aArgs = self::flattenArray($aArgs); + $sumArgs = self::flattenArray($sumArgs); + if (count($sumArgs) == 0) { + $sumArgs = $aArgs; + } + $condition = self::_ifCondition($condition); + // Loop through arguments + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + if ((is_null($returnValue)) || ($arg > $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + return $returnValue; + } // function MAXIF() + + /** * LARGE * @@ -1184,16 +1317,7 @@ class PHPExcel_Calculation_Functions { $returnValue = 0; $aArgs = self::flattenArray($aArgs); - $condition = self::flattenSingleValue($condition); - if (!in_array($condition{0},array('>', '<', '='))) { - if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } - $condition = '='.$condition; - } else { - preg_match('/([<>=]+)(.*)/',$condition,$matches); - list(,$operator,$operand) = $matches; - if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } - $condition = $operator.$operand; - } + $condition = self::_ifCondition($condition); // Loop through arguments foreach ($aArgs as $arg) { if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } @@ -1232,15 +1356,7 @@ class PHPExcel_Calculation_Functions { if (count($sumArgs) == 0) { $sumArgs = $aArgs; } - if (!in_array($condition{0},array('>', '<', '='))) { - if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } - $condition = '='.$condition; - } else { - preg_match('/([<>=]+)(.*)/',$condition,$matches); - list(,$operator,$operand) = $matches; - if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } - $condition = $operator.$operand; - } + $condition = self::_ifCondition($condition); // Loop through arguments foreach ($aArgs as $key => $arg) { if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } @@ -1348,6 +1464,52 @@ class PHPExcel_Calculation_Functions { } // function AVERAGEA() + /** + * AVERAGEIF + * + * Returns the average value from a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * AVERAGEIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be checked. + * @return float + */ + public static function AVERAGEIF($aArgs,$condition,$averageArgs = array()) { + // Return value + $returnValue = 0; + + $aArgs = self::flattenArray($aArgs); + $averageArgs = self::flattenArray($averageArgs); + if (count($averageArgs) == 0) { + $averageArgs = $aArgs; + } + $condition = self::_ifCondition($condition); + // Loop through arguments + $aCount = 0; + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + if ((is_null($returnValue)) || ($arg > $returnValue)) { + $returnValue += $arg; + ++$aCount; + } + } + } + + // Return + if ($aCount > 0) { + return $returnValue / $aCount; + } else { + return self::$_errorCodes['divisionbyzero']; + } + } // function AVERAGEIF() + + /** * MEDIAN * @@ -5529,7 +5691,7 @@ class PHPExcel_Calculation_Functions { * @return string Version information */ public static function VERSION() { - return 'PHPExcel 1.7.2, 2010-01-11'; + return 'PHPExcel 1.7.3, 2010-05-17'; } // function VERSION() @@ -5675,22 +5837,37 @@ class PHPExcel_Calculation_Functions { * depending on the value of the ReturnDateType flag */ public static function DATEVALUE($dateValue = 1) { - $dateValue = str_replace(array('/','.',' '),array('-','-','-'),trim(self::flattenSingleValue($dateValue),'"')); + $dateValue = trim(self::flattenSingleValue($dateValue),'"'); + // Strip any ordinals because they're allowed in Excel (English only) + $dateValue = preg_replace('/(\d)(st|nd|rd|th)([ -\/])/Ui','$1$3',$dateValue); + // Convert separators (/ . or space) to hyphens (should also handle dot used for ordinals in some countries, e.g. Denmark, Germany) + $dateValue = str_replace(array('/','.','-',' '),array(' ',' ',' ',' '),$dateValue); $yearFound = false; - $t1 = explode('-',$dateValue); + $t1 = explode(' ',$dateValue); foreach($t1 as &$t) { - if ((is_numeric($t)) && (($t > 31) && ($t < 100))) { + if ((is_numeric($t)) && ($t > 31)) { if ($yearFound) { return self::$_errorCodes['value']; } else { - $t += 1900; + if ($t < 100) { $t += 1900; } $yearFound = true; } } } + if ((count($t1) == 1) && (strpos($t,':') != false)) { + // We've been fed a time value without any date + return 0.0; + } elseif (count($t1) == 2) { + // We only have two parts of the date: either day/month or month/year + if ($yearFound) { + array_unshift($t1,1); + } else { + array_push($t1,date('Y')); + } + } unset($t); - $dateValue = implode('-',$t1); + $dateValue = implode(' ',$t1); $PHPDateArray = date_parse($dateValue); if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { @@ -5769,9 +5946,11 @@ class PHPExcel_Calculation_Functions { * depending on the value of the ReturnDateType flag */ public static function TIMEVALUE($timeValue) { - $timeValue = self::flattenSingleValue($timeValue); + $timeValue = trim(self::flattenSingleValue($timeValue),'"'); + $timeValue = str_replace(array('/','.'),array('-','-'),$timeValue); - if ((($PHPDateArray = date_parse($timeValue)) !== False) && ($PHPDateArray['error_count'] == 0)) { + $PHPDateArray = date_parse($timeValue); + if (($PHPDateArray !== False) && ($PHPDateArray['error_count'] == 0)) { if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($PHPDateArray['year'],$PHPDateArray['month'],$PHPDateArray['day'],$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second']); } else { @@ -6042,19 +6221,55 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } - if ((is_numeric($method)) && (!is_string($method))) { + if (((is_numeric($method)) && (!is_string($method))) || ($method == '')) { switch($method) { case 0 : return self::DAYS360($startDate,$endDate) / 360; break; case 1 : + $days = self::DATEDIF($startDate,$endDate); $startYear = self::YEAR($startDate); $endYear = self::YEAR($endDate); - $leapDay = 0; - if (self::_isLeapYear($startYear) || self::_isLeapYear($endYear)) { - $leapDay = 1; + $years = $endYear - $startYear + 1; + $leapDays = 0; + if ($years == 1) { + if (self::_isLeapYear($endYear)) { + $startMonth = self::MONTHOFYEAR($startDate); + $endMonth = self::MONTHOFYEAR($endDate); + $endDay = self::DAYOFMONTH($endDate); + if (($startMonth < 3) || + (($endMonth * 100 + $endDay) >= (2 * 100 + 29))) { + $leapDays += 1; + } + } + } else { + for($year = $startYear; $year <= $endYear; ++$year) { + if ($year == $startYear) { + $startMonth = self::MONTHOFYEAR($startDate); + $startDay = self::DAYOFMONTH($startDate); + if ($startMonth < 3) { + $leapDays += (self::_isLeapYear($year)) ? 1 : 0; + } + } elseif($year == $endYear) { + $endMonth = self::MONTHOFYEAR($endDate); + $endDay = self::DAYOFMONTH($endDate); + if (($endMonth * 100 + $endDay) >= (2 * 100 + 29)) { + $leapDays += (self::_isLeapYear($year)) ? 1 : 0; + } + } else { + $leapDays += (self::_isLeapYear($year)) ? 1 : 0; + } + } + if ($years == 2) { + if (($leapDays == 0) && (self::_isLeapYear($startYear)) && ($days > 365)) { + $leapDays = 1; + } elseif ($days < 366) { + $years = 1; + } + } + $leapDays /= $years; } - return self::DATEDIF($startDate,$endDate) / (365 + $leapDay); + return $days / (365 + $leapDays); break; case 2 : return self::DATEDIF($startDate,$endDate) / 360; @@ -6080,7 +6295,10 @@ class PHPExcel_Calculation_Functions { * @return long Interval between the dates */ public static function NETWORKDAYS($startDate,$endDate) { - // Flush the mandatory start and end date that are referenced in the function definition + // Retrieve the mandatory start and end date that are referenced in the function definition + $startDate = self::flattenSingleValue($startDate); + $endDate = self::flattenSingleValue($endDate); + // Flush the mandatory start and end date that are referenced in the function definition, and get the optional days $dateArgs = self::flattenArray(func_get_args()); array_shift($dateArgs); array_shift($dateArgs); @@ -6089,9 +6307,11 @@ class PHPExcel_Calculation_Functions { if (is_string($startDate = $sDate = self::_getDateValue($startDate))) { return self::$_errorCodes['value']; } + $startDate = (float) floor($startDate); if (is_string($endDate = $eDate = self::_getDateValue($endDate))) { return self::$_errorCodes['value']; } + $endDate = (float) floor($endDate); if ($sDate > $eDate) { $startDate = $eDate; @@ -6140,69 +6360,80 @@ class PHPExcel_Calculation_Functions { * @return long Interval between the dates */ public static function WORKDAY($startDate,$endDays) { + // Retrieve the mandatory start date and days that are referenced in the function definition + $startDate = self::flattenSingleValue($startDate); + $endDays = (int) self::flattenSingleValue($endDays); + // Flush the mandatory start date and days that are referenced in the function definition, and get the optional days $dateArgs = self::flattenArray(func_get_args()); - array_shift($dateArgs); array_shift($dateArgs); - if (is_string($startDate = self::_getDateValue($startDate))) { + if ((is_string($startDate = self::_getDateValue($startDate))) || (!is_numeric($endDays))) { return self::$_errorCodes['value']; } - if (!is_numeric($endDays)) { - return self::$_errorCodes['value']; - } - $endDate = (float) $startDate + (floor($endDays / 5) * 7) + ($endDays % 5); - if ($endDays < 0) { - $endDate += 7; + $startDate = (float) floor($startDate); + // If endDays is 0, we always return startDate + if ($endDays == 0) { return $startDate; } + + $decrementing = ($endDays < 0) ? True : False; + + // Adjust the start date if it falls over a weekend + + $startDoW = self::DAYOFWEEK($startDate,3); + if (self::DAYOFWEEK($startDate,3) >= 5) { + $startDate += ($decrementing) ? -$startDoW + 4: 7 - $startDoW; + ($decrementing) ? $endDays++ : $endDays--; } + // Add endDays + $endDate = (float) $startDate + (intval($endDays / 5) * 7) + ($endDays % 5); + + // Adjust the calculated end date if it falls over a weekend $endDoW = self::DAYOFWEEK($endDate,3); if ($endDoW >= 5) { - if ($endDays >= 0) { - $endDate += (7 - $endDoW); - } else { - $endDate -= ($endDoW - 5); - } + $endDate += ($decrementing) ? -$endDoW + 4: 7 - $endDoW; } // Test any extra holiday parameters if (count($dateArgs) > 0) { $holidayCountedArray = $holidayDates = array(); foreach ($dateArgs as $holidayDate) { - if (is_string($holidayDate = self::_getDateValue($holidayDate))) { - return self::$_errorCodes['value']; + if ((!is_null($holidayDate)) && (trim($holidayDate) > '')) { + if (is_string($holidayDate = self::_getDateValue($holidayDate))) { + return self::$_errorCodes['value']; + } + if (self::DAYOFWEEK($holidayDate,3) < 5) { + $holidayDates[] = $holidayDate; + } } - $holidayDates[] = $holidayDate; } - if ($endDays >= 0) { - sort($holidayDates, SORT_NUMERIC); - } else { + if ($decrementing) { rsort($holidayDates, SORT_NUMERIC); + } else { + sort($holidayDates, SORT_NUMERIC); } foreach ($holidayDates as $holidayDate) { - if ($endDays >= 0) { - if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { - if ((self::DAYOFWEEK($holidayDate,2) < 6) && (!in_array($holidayDate,$holidayCountedArray))) { - ++$endDate; - $holidayCountedArray[] = $holidayDate; - } - } - } else { + if ($decrementing) { if (($holidayDate <= $startDate) && ($holidayDate >= $endDate)) { - if ((self::DAYOFWEEK($holidayDate,2) < 6) && (!in_array($holidayDate,$holidayCountedArray))) { + if (!in_array($holidayDate,$holidayCountedArray)) { --$endDate; $holidayCountedArray[] = $holidayDate; } } - } - $endDoW = self::DAYOFWEEK($endDate,3); - if ($endDoW >= 5) { - if ($endDays >= 0) { - $endDate += (7 - $endDoW); - } else { - $endDate -= ($endDoW - 5); + } else { + if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { + if (!in_array($holidayDate,$holidayCountedArray)) { + ++$endDate; + $holidayCountedArray[] = $holidayDate; + } } } + // Adjust the calculated end date if it falls over a weekend + $endDoW = self::DAYOFWEEK($endDate,3); + if ($endDoW >= 5) { + $endDate += ($decrementing) ? -$endDoW + 4: 7 - $endDoW; + } + } } @@ -7064,12 +7295,13 @@ class PHPExcel_Calculation_Functions { * @return string */ public static function COMPLEX($realNumber=0.0, $imaginary=0.0, $suffix='i') { - $realNumber = self::flattenSingleValue($realNumber); - $imaginary = self::flattenSingleValue($imaginary); - $suffix = self::flattenSingleValue($suffix); + $realNumber = (is_null($realNumber)) ? 0.0 : (float) self::flattenSingleValue($realNumber); + $imaginary = (is_null($imaginary)) ? 0.0 : (float) self::flattenSingleValue($imaginary); + $suffix = (is_null($suffix)) ? 'i' : self::flattenSingleValue($suffix); if (((is_numeric($realNumber)) && (is_numeric($imaginary))) && (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))) { + if ($suffix == '') $suffix = 'i'; if ($realNumber == 0.0) { if ($imaginary == 0.0) { return (string) '0'; @@ -8371,14 +8603,15 @@ class PHPExcel_Calculation_Functions { * @return int */ public static function BESSELI($x, $n) { - $x = self::flattenSingleValue($x); - $n = floor(self::flattenSingleValue($n)); + $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); + $n = (is_null($n)) ? 0.0 : self::flattenSingleValue($n); if ((is_numeric($x)) && (is_numeric($n))) { + $n = floor($n); if ($n < 0) { return self::$_errorCodes['num']; } - $f_2_PI = 2 * pi(); + $f_2_PI = 2 * M_PI; if (abs($x) <= 30) { $fTerm = pow($x / 2, $n) / self::FACT($n); @@ -8413,10 +8646,11 @@ class PHPExcel_Calculation_Functions { * @return int */ public static function BESSELJ($x, $n) { - $x = self::flattenSingleValue($x); - $n = floor(self::flattenSingleValue($n)); + $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); + $n = (is_null($n)) ? 0.0 : self::flattenSingleValue($n); if ((is_numeric($x)) && (is_numeric($n))) { + $n = floor($n); if ($n < 0) { return self::$_errorCodes['num']; } @@ -8491,15 +8725,15 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function BESSELK($x, $ord) { - $x = self::flattenSingleValue($x); - $ord = floor(self::flattenSingleValue($ord)); + $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); + $ord = (is_null($ord)) ? 0.0 : self::flattenSingleValue($ord); if ((is_numeric($x)) && (is_numeric($ord))) { - if ($ord < 0) { + if (($ord < 0) || ($x == 0.0)) { return self::$_errorCodes['num']; } - switch($ord) { + switch(floor($ord)) { case 0 : return self::_Besselk0($x); break; case 1 : return self::_Besselk1($x); @@ -8569,15 +8803,15 @@ class PHPExcel_Calculation_Functions { * @return int */ public static function BESSELY($x, $ord) { - $x = self::flattenSingleValue($x); - $ord = floor(self::flattenSingleValue($ord)); + $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); + $ord = (is_null($ord)) ? 0.0 : self::flattenSingleValue($ord); if ((is_numeric($x)) && (is_numeric($ord))) { - if ($ord < 0) { + if (($ord < 0) || ($x == 0.0)) { return self::$_errorCodes['num']; } - switch($ord) { + switch(floor($ord)) { case 0 : return self::_Bessely0($x); break; case 1 : return self::_Bessely1($x); @@ -9631,7 +9865,7 @@ class PHPExcel_Calculation_Functions { $daysPerYear = 365; break; case 1 : - if (self::_isLeapYear(self::YEAR($year))) { + if (self::_isLeapYear($year)) { $daysPerYear = 366; } else { $daysPerYear = 365; @@ -9680,13 +9914,8 @@ class PHPExcel_Calculation_Functions { if (!is_numeric($daysBetweenIssueAndSettlement)) { return $daysBetweenIssueAndSettlement; } - $daysPerYear = self::_daysPerYear(self::YEAR($issue),$basis); - if (!is_numeric($daysPerYear)) { - return $daysPerYear; - } - $daysBetweenIssueAndSettlement *= $daysPerYear; - return $par * $rate * ($daysBetweenIssueAndSettlement / $daysPerYear); + return $par * $rate * $daysBetweenIssueAndSettlement; } return self::$_errorCodes['value']; } // function ACCRINT() @@ -9725,13 +9954,7 @@ class PHPExcel_Calculation_Functions { if (!is_numeric($daysBetweenIssueAndSettlement)) { return $daysBetweenIssueAndSettlement; } - $daysPerYear = self::_daysPerYear(self::YEAR($issue),$basis); - if (!is_numeric($daysPerYear)) { - return $daysPerYear; - } - $daysBetweenIssueAndSettlement *= $daysPerYear; - - return $par * $rate * ($daysBetweenIssueAndSettlement / $daysPerYear); + return $par * $rate * $daysBetweenIssueAndSettlement; } return self::$_errorCodes['value']; } // function ACCRINTM() @@ -9744,7 +9967,7 @@ class PHPExcel_Calculation_Functions { $salvage = self::flattenSingleValue($salvage); $period = floor(self::flattenSingleValue($period)); $rate = self::flattenSingleValue($rate); - $basis = floor(self::flattenSingleValue($basis)); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); $fUsePer = 1.0 / $rate; @@ -9759,18 +9982,22 @@ class PHPExcel_Calculation_Functions { } $rate *= $amortiseCoeff; - $fNRate = floor((self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost) + 0.5); +// $fNRate = floor((self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost) + 0.5); + $fNRate = round(self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost,0); $cost -= $fNRate; $fRest = $cost - $salvage; for ($n = 0; $n < $period; ++$n) { - $fNRate = floor(($rate * $cost) + 0.5); +// $fNRate = floor(($rate * $cost) + 0.5); + $fNRate = round($rate * $cost,0); $fRest -= $fNRate; if ($fRest < 0.0) { switch ($period - $n) { case 0 : - case 1 : return floor(($cost * 0.5) + 0.5); + case 1 : +// return floor(($cost * 0.5) + 0.5); + return round($cost * 0.5,0); break; default : return 0.0; break; @@ -9789,11 +10016,17 @@ class PHPExcel_Calculation_Functions { $salvage = self::flattenSingleValue($salvage); $period = self::flattenSingleValue($period); $rate = self::flattenSingleValue($rate); - $basis = self::flattenSingleValue($basis); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); $fOneRate = $cost * $rate; $fCostDelta = $cost - $salvage; - $f0Rate = self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost; + // Note, quirky variation for leap years on the YEARFRAC for this function + $purchasedYear = self::YEAR($purchased); + $yearFrac = self::YEARFRAC($purchased, $firstPeriod, $basis); + if (($basis == 1) && ($yearFrac < 1) && (self::_isLeapYear($purchasedYear))) { + $yearFrac *= 365 / 366; + } + $f0Rate = $yearFrac * $rate * $cost; $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate); if ($period == 0) { @@ -9808,12 +10041,205 @@ class PHPExcel_Calculation_Functions { } // function AMORLINC() + private static function _lastDayOfMonth($testDate) { + $date = clone $testDate; + $date->modify('+1 day'); + return ($date->format('d') == 1); + } // function _lastDayOfMonth() + + private static function _firstDayOfMonth($testDate) { + $date = clone $testDate; + return ($date->format('d') == 1); + } // function _lastDayOfMonth() + + private static function _coupFirstPeriodDate($settlement, $maturity, $frequency, $next) { + $months = 12 / $frequency; + + $result = PHPExcel_Shared_Date::ExcelToPHPObject($maturity); + $eom = self::_lastDayOfMonth($result); + + while ($settlement < PHPExcel_Shared_Date::PHPToExcel($result)) { + $result->modify('-'.$months.' months'); + } + if ($next) { + $result->modify('+'.$months.' months'); + } + + if ($eom) { + $result->modify('-1 day'); + } + + return PHPExcel_Shared_Date::PHPToExcel($result); + } // function _coupFirstPeriodDate() + + + private static function _validFrequency($frequency) { + if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) { + return true; + } + if ((self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) && + (($frequency == 6) || ($frequency == 12))) { + return true; + } + return false; + } // function _validFrequency() + + public static function COUPDAYS($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; + } + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + switch ($basis) { + case 3: // Actual/365 + return 365 / $frequency; + case 1: // Actual/actual + if ($frequency == 1) { + $daysPerYear = self::_daysPerYear(self::YEAR($maturity),$basis); + return ($daysPerYear / $frequency); + } else { + $prev = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); + $next = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + return ($next - $prev); + } + default: // US (NASD) 30/360, Actual/360 or European 30/360 + return 360 / $frequency; + } + return self::$_errorCodes['value']; + } // function COUPDAYS() + + + public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; + } + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); + $prev = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); + + return self::YEARFRAC($prev, $settlement, $basis) * $daysPerYear; + } // function COUPDAYBS() + + + public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; + } + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); + $next = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + + return self::YEARFRAC($settlement, $next, $basis) * $daysPerYear; + } // function COUPDAYSNC() + + + public static function COUPNCD($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; + } + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + return self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + } // function COUPNCD() + + + public static function COUPPCD($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; + } + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + return self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); + } // function COUPPCD() + + public static function COUPNUM($settlement, $maturity, $frequency, $basis=0) { $settlement = self::flattenSingleValue($settlement); $maturity = self::flattenSingleValue($maturity); - $frequency = self::flattenSingleValue($frequency); - $basis = self::flattenSingleValue($basis); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; + } + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + $settlement = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; switch ($frequency) { @@ -9823,29 +10249,54 @@ class PHPExcel_Calculation_Functions { return ceil($daysBetweenSettlementAndMaturity / 180); case 4: // quarterly return ceil($daysBetweenSettlementAndMaturity / 90); + case 6: // bimonthly + return ceil($daysBetweenSettlementAndMaturity / 60); + case 12: // monthly + return ceil($daysBetweenSettlementAndMaturity / 30); } return self::$_errorCodes['value']; } // function COUPNUM() - public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) { + public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis=0) { $settlement = self::flattenSingleValue($settlement); $maturity = self::flattenSingleValue($maturity); - $frequency = self::flattenSingleValue($frequency); - $basis = self::flattenSingleValue($basis); + $rate = (float) self::flattenSingleValue($rate); + $yield = (float) self::flattenSingleValue($yield); + $redemption = (float) self::flattenSingleValue($redemption); + $frequency = (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; - - switch ($frequency) { - case 1: // annual payments - return 365 - ($daysBetweenSettlementAndMaturity % 360); - case 2: // half-yearly - return 365 - ($daysBetweenSettlementAndMaturity % 360); - case 4: // quarterly - return self::DATEDIF($maturity, $settlement); + if (is_string($settlement = self::_getDateValue($settlement))) { + return self::$_errorCodes['value']; } - return self::$_errorCodes['value']; - } // function COUPDAYBS() + if (is_string($maturity = self::_getDateValue($maturity))) { + return self::$_errorCodes['value']; + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return self::$_errorCodes['num']; + } + + $dsc = self::COUPDAYSNC($settlement, $maturity, $frequency, $basis); + $e = self::COUPDAYS($settlement, $maturity, $frequency, $basis); + $n = self::COUPNUM($settlement, $maturity, $frequency, $basis); + $a = self::COUPDAYBS($settlement, $maturity, $frequency, $basis); + + $baseYF = 1.0 + ($yield / $frequency); + $rfp = 100 * ($rate / $frequency); + $de = $dsc / $e; + + $result = $redemption / pow($baseYF, (--$n + $de)); + for($k = 0; $k <= $n; ++$k) { + $result += $rfp / (pow($baseYF, ($k + $de))); + } + $result -= $rfp * ($a / $e); + + return $result; + } // function PRICE() /** @@ -10444,7 +10895,9 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } - $isMatrix = (is_numeric(array_shift(array_keys($cellAddress)))); + $x = array_keys($cellAddress); + $x = array_shift($x); + $isMatrix = (is_numeric($x)); list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); if ($isMatrix) { @@ -10511,7 +10964,8 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } - $isMatrix = (is_numeric(array_shift(array_keys($cellAddress)))); + $i = array_keys($cellAddress); + $isMatrix = (is_numeric(array_shift($i))); list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); if ($isMatrix) { @@ -10581,11 +11035,16 @@ class PHPExcel_Calculation_Functions { * @return string A reference to a cell or range of cells */ public static function OFFSET($cellAddress=Null,$rows=0,$columns=0,$height=null,$width=null) { + $rows = self::flattenSingleValue($rows); + $columns = self::flattenSingleValue($columns); + $height = self::flattenSingleValue($height); + $width = self::flattenSingleValue($width); if ($cellAddress == Null) { return 0; } - $pCell = array_pop(func_get_args()); + $args = func_get_args(); + $pCell = array_pop($args); if (!is_object($pCell)) { return self::$_errorCodes['reference']; } @@ -10791,6 +11250,8 @@ class PHPExcel_Calculation_Functions { /** + * INDEX + * * Uses an index to choose a value from a reference or array * implemented: Return the value of a specified cell or array of cells Array form * not implemented: Return a reference to specified cells Reference form @@ -10805,6 +11266,10 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } + if (!is_array($arrayValues)) { + return self::$_errorCodes['reference']; + } + $rowKeys = array_keys($arrayValues); $columnKeys = @array_keys($arrayValues[$rowKeys[0]]); @@ -10841,6 +11306,102 @@ class PHPExcel_Calculation_Functions { } // function INDEX() + /** + * N + * + * Returns a value converted to a number + * + * @param value The value you want converted + * @return number N converts values listed in the following table + * If value is or refers to N returns + * A number That number + * A date The serial number of that date + * TRUE 1 + * FALSE 0 + * An error value The error value + * Anything else 0 + */ + public static function N($value) { + while (is_array($value)) { + $value = array_shift($value); + } + + switch (gettype($value)) { + case 'double' : + case 'float' : + case 'integer' : + return $value; + break; + case 'boolean' : + return (integer) $value; + break; + case 'string' : + // Errors + if ((strlen($value) > 0) && ($value{0} == '#')) { + return $value; + } + break; + } + return 0; + } // function N() + + + /** + * TYPE + * + * Returns a number that identifies the type of a value + * + * @param value The value you want tested + * @return number N converts values listed in the following table + * If value is or refers to N returns + * A number 1 + * Text 2 + * Logical Value 4 + * An error value 16 + * Array or Matrix 64 + */ + public static function TYPE($value) { + $value = self::flattenArrayIndexed($value); + if (is_array($value) && (count($value) > 1)) { + $a = array_keys($value); + $a = array_pop($a); + // Range of cells is an error + if (self::isCellValue($a)) { + return 16; + // Test for Matrix + } elseif (self::isMatrixValue($a)) { + return 64; + } + } elseif(count($value) == 0) { + // Empty Cell + return 1; + } + $value = self::flattenSingleValue($value); + + switch (gettype($value)) { + case 'double' : + case 'float' : + case 'integer' : + return 1; + break; + case 'boolean' : + return 4; + break; + case 'array' : + return 64; + break; + case 'string' : + // Errors + if ((strlen($value) > 0) && ($value{0} == '#')) { + return 16; + } + return 2; + break; + } + return 0; + } // function TYPE() + + /** * SYD * @@ -11132,7 +11693,8 @@ class PHPExcel_Calculation_Functions { private static function _vlookupSort($a,$b) { - $firstColumn = array_shift(array_keys($a)); + $f = array_keys($a); + $firstColumn = array_shift($f); if (strtolower($a[$firstColumn]) == strtolower($b[$firstColumn])) { return 0; } @@ -11150,6 +11712,10 @@ class PHPExcel_Calculation_Functions { * @return mixed The value of the found cell */ public static function VLOOKUP($lookup_value, $lookup_array, $index_number, $not_exact_match=true) { + $lookup_value = self::flattenSingleValue($lookup_value); + $index_number = self::flattenSingleValue($index_number); + $not_exact_match = self::flattenSingleValue($not_exact_match); + // index_number must be greater than or equal to 1 if ($index_number < 1) { return self::$_errorCodes['value']; @@ -11159,7 +11725,8 @@ class PHPExcel_Calculation_Functions { if ((!is_array($lookup_array)) || (count($lookup_array) < 1)) { return self::$_errorCodes['reference']; } else { - $firstRow = array_pop(array_keys($lookup_array)); + $f = array_keys($lookup_array); + $firstRow = array_pop($f); if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { return self::$_errorCodes['reference']; } else { @@ -11211,22 +11778,28 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['na']; } $lookupRows = count($lookup_vector); - $lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]); + $l = array_keys($lookup_vector); + $l = array_shift($l); + $lookupColumns = count($lookup_vector[$l]); if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) { $lookup_vector = self::TRANSPOSE($lookup_vector); $lookupRows = count($lookup_vector); - $lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]); + $l = array_keys($lookup_vector); + $lookupColumns = count($lookup_vector[array_shift($l)]); } if (is_null($result_vector)) { $result_vector = $lookup_vector; } $resultRows = count($result_vector); - $resultColumns = count($result_vector[array_shift(array_keys($result_vector))]); + $l = array_keys($result_vector); + $l = array_shift($l); + $resultColumns = count($result_vector[$l]); if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) { $result_vector = self::TRANSPOSE($result_vector); $resultRows = count($result_vector); - $resultColumns = count($result_vector[array_shift(array_keys($result_vector))]); + $r = array_keys($result_vector); + $resultColumns = count($result_vector[array_shift($r)]); } if ($lookupRows == 2) { @@ -11236,7 +11809,8 @@ class PHPExcel_Calculation_Functions { if ($lookupColumns != 2) { foreach($lookup_vector as &$value) { if (is_array($value)) { - $key1 = $key2 = array_shift(array_keys($value)); + $k = array_keys($value); + $key1 = $key2 = array_shift($k); $key2++; $dataValue1 = $value[$key1]; } else { @@ -11328,9 +11902,10 @@ class PHPExcel_Calculation_Functions { * @return mixed */ public static function flattenSingleValue($value = '') { - if (is_array($value)) { - return self::flattenSingleValue(array_pop($value)); + while (is_array($value)) { + $value = array_pop($value); } + return $value; } // function flattenSingleValue() diff --git a/libraries/PHPExcel/PHPExcel/Cell.php b/libraries/PHPExcel/PHPExcel/Cell.php index c0603ac16..8855f19d9 100644 --- a/libraries/PHPExcel/PHPExcel/Cell.php +++ b/libraries/PHPExcel/PHPExcel/Cell.php @@ -22,43 +22,10 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Cell_DataValidation */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataValidation.php'; - -/** PHPExcel_Cell_Hyperlink */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/Hyperlink.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Calculation */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; - -/** PHPExcel_Cell_IValueBinder */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/IValueBinder.php'; - -/** PHPExcel_Cell_DefaultValueBinder */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DefaultValueBinder.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - - /** * PHPExcel_Cell * @@ -124,6 +91,24 @@ class PHPExcel_Cell */ private $_xfIndex; + + /** + * Send notification to the cache controller + * @return void + **/ + public function notifyCacheController() { + $this->_parent->getCellCacheController()->updateCacheData($this); + } + + public function detach() { + $this->_parent = null; + } + + public function attach($parent) { + $this->_parent = $parent; + } + + /** * Create a new Cell * @@ -256,11 +241,13 @@ class PHPExcel_Cell // set the datatype $this->_dataType = $pDataType; + + $this->notifyCacheController(); return $this; } /** - * Get caluclated cell value + * Get calculated cell value * * @return mixed */ @@ -271,9 +258,11 @@ class PHPExcel_Cell try { // echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value
'; $result = PHPExcel_Calculation::getInstance()->calculateCellValue($this,$resetLog); +// echo $this->getCoordinate().' calculation result is '.$result.'
'; } catch ( Exception $ex ) { // echo 'Calculation Exception: '.$ex->getMessage().'
'; $result = '#N/A'; + throw(new Exception($ex->getMessage())); } if ((is_string($result)) && ($result == '#Not Yet Implemented')) { @@ -308,6 +297,8 @@ class PHPExcel_Cell if (!is_null($pValue)) { $this->_calculatedValue = $pValue; } + + $this->notifyCacheController(); return $this; } @@ -340,6 +331,8 @@ class PHPExcel_Cell public function setDataType($pDataType = PHPExcel_Cell_DataType::TYPE_STRING) { $this->_dataType = $pDataType; + + $this->notifyCacheController(); return $this; } @@ -386,6 +379,8 @@ class PHPExcel_Cell } $this->_parent->setDataValidation($this->getCoordinate(), $pDataValidation); + + $this->notifyCacheController(); return $this; } @@ -433,6 +428,8 @@ class PHPExcel_Cell } $this->_parent->setHyperlink($this->getCoordinate(), $pHyperlink); + + $this->notifyCacheController(); return $this; } @@ -453,6 +450,8 @@ class PHPExcel_Cell */ public function rebindParent(PHPExcel_Worksheet $parent) { $this->_parent = $parent; + + $this->notifyCacheController(); return $this; } @@ -616,6 +615,30 @@ class PHPExcel_Cell return array( ($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1) ); } + /** + * Calculate range boundaries + * + * @param string $pRange Cell range (e.g. A1:A1) + * @return array Range boundaries (staring Column, starting Row, Final Column, Final Row) + */ + public static function getRangeBoundaries($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + // Extract range + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } + + return array( self::coordinateFromString($rangeA), self::coordinateFromString($rangeB)); + } + /** * Column index from string * @@ -625,6 +648,14 @@ class PHPExcel_Cell */ public static function columnIndexFromString($pString = 'A') { + static $lookup = array( + '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, + '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 + ); + + if (isset($lookup[$pString])) + return $lookup[$pString]; + // Convert to uppercase $pString = strtoupper($pString); @@ -809,6 +840,8 @@ class PHPExcel_Cell public function setXfIndex($pValue = 0) { $this->_xfIndex = $pValue; + + $this->notifyCacheController(); return $this; } diff --git a/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php index d8e25645c..02193ed64 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,37 +22,10 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Cell_IValueBinder */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/IValueBinder.php'; - -/** PHPExcel_Cell_DefaultValueBinder */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DefaultValueBinder.php'; - -/** PHPExcel_Style_NumberFormat */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - - /** * PHPExcel_Cell_AdvancedValueBinder * @@ -78,49 +51,72 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder // Find out data type $dataType = parent::dataTypeForValue($value); - + // Style logic - strings if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) { // Check for percentage if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { // Convert value to number $cell->setValueExplicit( (float)str_replace('%', '', $value) / 100, PHPExcel_Cell_DataType::TYPE_NUMERIC); - + // Set style $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE ); - + return true; } - - // Check for time e.g. '9:45', '09:45' + + // Check for time without seconds e.g. '9:45', '09:45' if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { list($h, $m) = explode(':', $value); $days = $h / 24 + $m / 1440; - + // Convert value to number $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); - + // Set style $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 ); - + return true; } - - // Check for date - if (strtotime($value) !== false) { - // make sure we have UTC for the sake of strtotime - $saveTimeZone = date_default_timezone_get(); - date_default_timezone_set('UTC'); - - // Convert value to Excel date - $cell->setValueExplicit( PHPExcel_Shared_Date::PHPToExcel(strtotime($value)), PHPExcel_Cell_DataType::TYPE_NUMERIC); - + + // Check for time with seconds '9:45:59', '09:45:59' + if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { + list($h, $m, $s) = explode(':', $value); + $days = $h / 24 + $m / 1440 + $s / 86400; + + // Convert value to number + $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2 ); - - // restore original value for timezone - date_default_timezone_set($saveTimeZone); - + $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 ); + + return true; + } + + // Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' + if (($v = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { + // Convert value to Excel date + $cell->setValueExplicit($v, PHPExcel_Cell_DataType::TYPE_NUMERIC); + + // Set style. Either there is a time part or not. Look for ':' + if (strpos($value, ':') !== false) { + $formatCode = 'yyyy-mm-dd h:mm'; + } else { + $formatCode = 'yyyy-mm-dd'; + } + $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode($formatCode); + + return true; + } + + // Check for newline character "\n" + if (strpos($value, "\n") !== false) { + $value = PHPExcel_Shared_String::SanitizeUTF8($value); + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); + + // Set style + $cell->getParent()->getStyle( $cell->getCoordinate() )->getAlignment()->setWrapText(true); + return true; } } diff --git a/libraries/PHPExcel/PHPExcel/Cell/DataType.php b/libraries/PHPExcel/PHPExcel/Cell/DataType.php index add1bec8b..20e4ff8c3 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DataType.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DataType.php @@ -22,22 +22,10 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Cell_DefaultValueBinder */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DefaultValueBinder.php'; - - /** * PHPExcel_Cell_DataType * @@ -71,7 +59,7 @@ class PHPExcel_Cell_DataType public static function getErrorCodes() { return self::$_errorCodes; } - + /** * DataType for value * diff --git a/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php b/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php index 8d7f29329..f0b939105 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php @@ -22,7 +22,7 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -151,20 +151,12 @@ class PHPExcel_Cell_DataValidation */ private $_prompt; - /** - * Parent cell - * - * @var PHPExcel_Cell - */ - private $_parent; - /** * Create a new PHPExcel_Cell_DataValidation * - * @param PHPExcel_Cell $pCell Parent cell * @throws Exception */ - public function __construct(PHPExcel_Cell $pCell = null) + public function __construct() { // Initialise member variables $this->_formula1 = ''; @@ -180,9 +172,6 @@ class PHPExcel_Cell_DataValidation $this->_error = ''; $this->_promptTitle = ''; $this->_prompt = ''; - - // Set cell - $this->_parent = $pCell; } /** @@ -445,26 +434,6 @@ class PHPExcel_Cell_DataValidation return $this; } - /** - * Get parent - * - * @return PHPExcel_Cell - */ - public function getParent() { - return $this->_parent; - } - - /** - * Set Parent - * - * @param PHPExcel_Cell $value - * @return PHPExcel_Cell_DataValidation - */ - public function setParent($value = null) { - $this->_parent = $value; - return $this; - } - /** * Get hash code * @@ -485,7 +454,6 @@ class PHPExcel_Cell_DataValidation . $this->_error . $this->_promptTitle . $this->_prompt - . $this->_parent->getCoordinate() . __CLASS__ ); } @@ -494,12 +462,9 @@ class PHPExcel_Cell_DataValidation * Implement PHP __clone to create a deep clone, not just a shallow copy. */ public function __clone() { - // unbind parent - $this->setParent(null); - $vars = get_object_vars($this); foreach ($vars as $key => $value) { - if (is_object($value) && $key != '_parent') { + if (is_object($value)) { $this->$key = clone $value; } else { $this->$key = $value; diff --git a/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php index 2b8bef72e..9476d9ead 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,31 +22,10 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Cell_IValueBinder */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/IValueBinder.php'; - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - - /** * PHPExcel_Cell_DefaultValueBinder * @@ -72,11 +51,11 @@ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder // Set value explicit $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::dataTypeForValue($value) ); - + // Done! return true; } - + /** * DataType for value * @@ -94,7 +73,7 @@ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder } elseif ($pValue instanceof PHPExcel_RichText) { return PHPExcel_Cell_DataType::TYPE_STRING; - } elseif ($pValue{0} === '=') { + } elseif ($pValue{0} === '=' && strlen($pValue) > 1) { return PHPExcel_Cell_DataType::TYPE_FORMULA; } elseif (is_bool($pValue)) { diff --git a/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php b/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php index a4f3758f4..f6af8adab 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php +++ b/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php @@ -22,7 +22,7 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -35,13 +35,6 @@ */ class PHPExcel_Cell_Hyperlink { - /** - * Cell representing the hyperlink - * - * @var PHPExcel_Cell - */ - private $_cell; - /** * URL to link the cell to * @@ -59,19 +52,15 @@ class PHPExcel_Cell_Hyperlink /** * Create a new PHPExcel_Cell_Hyperlink * - * @param PHPExcel_Cell $pCell Parent cell * @param string $pUrl Url to link the cell to * @param string $pTooltip Tooltip to display on the hyperlink * @throws Exception */ - public function __construct(PHPExcel_Cell $pCell = null, $pUrl = '', $pTooltip = '') + public function __construct($pUrl = '', $pTooltip = '') { // Initialise member variables $this->_url = $pUrl; $this->_tooltip = $pTooltip; - - // Set cell - $this->_parent = $pCell; } /** @@ -123,26 +112,6 @@ class PHPExcel_Cell_Hyperlink return strpos($this->_url, 'sheet://') !== false; } - /** - * Get parent - * - * @return PHPExcel_Cell - */ - public function getParent() { - return $this->_parent; - } - - /** - * Set Parent - * - * @param PHPExcel_Cell $value - * @return PHPExcel_Cell_Hyperlink - */ - public function setParent($value = null) { - $this->_parent = $value; - return $this; - } - /** * Get hash code * @@ -152,7 +121,6 @@ class PHPExcel_Cell_Hyperlink return md5( $this->_url . $this->_tooltip - . $this->_parent->getCoordinate() . __CLASS__ ); } diff --git a/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php index 3a4186ccf..39a9e9321 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Cell * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - - /** * PHPExcel_Cell_IValueBinder * diff --git a/libraries/PHPExcel/PHPExcel/Comment.php b/libraries/PHPExcel/PHPExcel/Comment.php index ee7254ac0..97f93da88 100644 --- a/libraries/PHPExcel/PHPExcel/Comment.php +++ b/libraries/PHPExcel/PHPExcel/Comment.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,28 +22,10 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel_RichText */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Comment * @@ -59,59 +41,59 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @var string */ private $_author; - + /** * Rich text comment * * @var PHPExcel_RichText */ private $_text; - + /** * Comment width (CSS style, i.e. XXpx or YYpt) * * @var string */ private $_width = '96pt'; - + /** * Left margin (CSS style, i.e. XXpx or YYpt) * * @var string */ private $_marginLeft = '59.25pt'; - + /** * Top margin (CSS style, i.e. XXpx or YYpt) * * @var string */ private $_marginTop = '1.5pt'; - + /** * Visible * * @var boolean */ private $_visible = false; - + /** * Comment height (CSS style, i.e. XXpx or YYpt) * * @var string */ private $_height = '55.5pt'; - + /** * Comment fill color * * @var PHPExcel_Style_Color */ private $_fillColor; - + /** * Create a new PHPExcel_Comment - * + * * @throws Exception */ public function __construct() @@ -121,7 +103,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_text = new PHPExcel_RichText(); $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); } - + /** * Get Author * @@ -130,7 +112,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getAuthor() { return $this->_author; } - + /** * Set Author * @@ -141,7 +123,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_author = $pValue; return $this; } - + /** * Get Rich text comment * @@ -150,7 +132,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getText() { return $this->_text; } - + /** * Set Rich text comment * @@ -161,7 +143,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_text = $pValue; return $this; } - + /** * Get comment width (CSS style, i.e. XXpx or YYpt) * @@ -170,7 +152,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getWidth() { return $this->_width; } - + /** * Set comment width (CSS style, i.e. XXpx or YYpt) * @@ -181,7 +163,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_width = $value; return $this; } - + /** * Get comment height (CSS style, i.e. XXpx or YYpt) * @@ -190,7 +172,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getHeight() { return $this->_height; } - + /** * Set comment height (CSS style, i.e. XXpx or YYpt) * @@ -201,7 +183,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_height = $value; return $this; } - + /** * Get left margin (CSS style, i.e. XXpx or YYpt) * @@ -210,7 +192,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getMarginLeft() { return $this->_marginLeft; } - + /** * Set left margin (CSS style, i.e. XXpx or YYpt) * @@ -221,7 +203,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_marginLeft = $value; return $this; } - + /** * Get top margin (CSS style, i.e. XXpx or YYpt) * @@ -230,7 +212,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getMarginTop() { return $this->_marginTop; } - + /** * Set top margin (CSS style, i.e. XXpx or YYpt) * @@ -241,7 +223,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable $this->_marginTop = $value; return $this; } - + /** * Is the comment visible by default? * @@ -250,7 +232,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getVisible() { return $this->_visible; } - + /** * Set comment default visibility * @@ -258,10 +240,10 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @return PHPExcel_Comment */ public function setVisible($value = false) { - $this->_visible = $value; + $this->_visible = $value; return $this; } - + /** * Get fill color * @@ -270,12 +252,12 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function getFillColor() { return $this->_fillColor; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_author @@ -289,7 +271,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/DocumentProperties.php b/libraries/PHPExcel/PHPExcel/DocumentProperties.php index 41fe1fb7d..ee8160c6f 100644 --- a/libraries/PHPExcel/PHPExcel/DocumentProperties.php +++ b/libraries/PHPExcel/PHPExcel/DocumentProperties.php @@ -22,7 +22,7 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/DocumentSecurity.php b/libraries/PHPExcel/PHPExcel/DocumentSecurity.php index 6344d40e3..2c5543866 100644 --- a/libraries/PHPExcel/PHPExcel/DocumentSecurity.php +++ b/libraries/PHPExcel/PHPExcel/DocumentSecurity.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel_Shared_PasswordHasher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; - - /** * PHPExcel_DocumentSecurity * @@ -53,35 +41,35 @@ class PHPExcel_DocumentSecurity * @var boolean */ private $_lockRevision; - + /** * LockStructure * * @var boolean */ private $_lockStructure; - + /** * LockWindows * * @var boolean */ private $_lockWindows; - + /** * RevisionsPassword * * @var string */ private $_revisionsPassword; - + /** * WorkbookPassword * * @var string */ private $_workbookPassword; - + /** * Create a new PHPExcel_DocumentSecurity */ @@ -94,7 +82,7 @@ class PHPExcel_DocumentSecurity $this->_revisionsPassword = ''; $this->_workbookPassword = ''; } - + /** * Is some sort of dcument security enabled? * @@ -105,7 +93,7 @@ class PHPExcel_DocumentSecurity $this->_lockStructure || $this->_lockWindows; } - + /** * Get LockRevision * @@ -114,7 +102,7 @@ class PHPExcel_DocumentSecurity function getLockRevision() { return $this->_lockRevision; } - + /** * Set LockRevision * @@ -125,7 +113,7 @@ class PHPExcel_DocumentSecurity $this->_lockRevision = $pValue; return $this; } - + /** * Get LockStructure * @@ -134,7 +122,7 @@ class PHPExcel_DocumentSecurity function getLockStructure() { return $this->_lockStructure; } - + /** * Set LockStructure * @@ -145,7 +133,7 @@ class PHPExcel_DocumentSecurity $this->_lockStructure = $pValue; return $this; } - + /** * Get LockWindows * @@ -154,7 +142,7 @@ class PHPExcel_DocumentSecurity function getLockWindows() { return $this->_lockWindows; } - + /** * Set LockWindows * @@ -165,7 +153,7 @@ class PHPExcel_DocumentSecurity $this->_lockWindows = $pValue; return $this; } - + /** * Get RevisionsPassword (hashed) * @@ -174,7 +162,7 @@ class PHPExcel_DocumentSecurity function getRevisionsPassword() { return $this->_revisionsPassword; } - + /** * Set RevisionsPassword * @@ -189,7 +177,7 @@ class PHPExcel_DocumentSecurity $this->_revisionsPassword = $pValue; return $this; } - + /** * Get WorkbookPassword (hashed) * diff --git a/libraries/PHPExcel/PHPExcel/HashTable.php b/libraries/PHPExcel/PHPExcel/HashTable.php index afbced953..795d538eb 100644 --- a/libraries/PHPExcel/PHPExcel/HashTable.php +++ b/libraries/PHPExcel/PHPExcel/HashTable.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_HashTable * @@ -53,14 +41,14 @@ class PHPExcel_HashTable * @var array */ public $_items = array(); - + /** * HashTable key map * * @var array */ public $_keyMap = array(); - + /** * Create a new PHPExcel_HashTable * @@ -74,7 +62,7 @@ class PHPExcel_HashTable $this->addFromSource($pSource); } } - + /** * Add HashTable items from source * @@ -88,7 +76,7 @@ class PHPExcel_HashTable } else if (!is_array($pSource)) { throw new Exception('Invalid array parameter passed.'); } - + foreach ($pSource as $item) { $this->add($item); } @@ -106,7 +94,7 @@ class PHPExcel_HashTable $this->_keyMap[ count($this->_items) - 1 ] = $pSource->getHashCode(); } } - + /** * Remove HashTable item * @@ -116,21 +104,21 @@ class PHPExcel_HashTable public function remove(PHPExcel_IComparable $pSource = null) { if (isset($this->_items[ $pSource->getHashCode() ])) { unset($this->_items[ $pSource->getHashCode() ]); - + $deleteKey = -1; - foreach ($this->_keyMap as $key => $value) { + foreach ($this->_keyMap as $key => $value) { if ($deleteKey >= 0) { $this->_keyMap[$key - 1] = $value; } - + if ($value == $pSource->getHashCode()) { $deleteKey = $key; } } - unset($this->_keyMap[ count($this->_keyMap) - 1 ]); - } + unset($this->_keyMap[ count($this->_keyMap) - 1 ]); + } } - + /** * Clear HashTable * @@ -139,7 +127,7 @@ class PHPExcel_HashTable $this->_items = array(); $this->_keyMap = array(); } - + /** * Count * @@ -148,7 +136,7 @@ class PHPExcel_HashTable public function count() { return count($this->_items); } - + /** * Get index for hash code * @@ -158,7 +146,7 @@ class PHPExcel_HashTable public function getIndexForHashCode($pHashCode = '') { return array_search($pHashCode, $this->_keyMap); } - + /** * Get by index * @@ -170,10 +158,10 @@ class PHPExcel_HashTable if (isset($this->_keyMap[$pIndex])) { return $this->getByHashCode( $this->_keyMap[$pIndex] ); } - + return null; } - + /** * Get by hashcode * @@ -185,10 +173,10 @@ class PHPExcel_HashTable if (isset($this->_items[$pHashCode])) { return $this->_items[$pHashCode]; } - + return null; } - + /** * HashTable to array * @@ -197,7 +185,7 @@ class PHPExcel_HashTable public function toArray() { return $this->_items; } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/IComparable.php b/libraries/PHPExcel/PHPExcel/IComparable.php index 1a3a689ea..a389325cb 100644 --- a/libraries/PHPExcel/PHPExcel/IComparable.php +++ b/libraries/PHPExcel/PHPExcel/IComparable.php @@ -20,7 +20,7 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/IOFactory.php b/libraries/PHPExcel/PHPExcel/IOFactory.php index f116bc012..7182c073a 100644 --- a/libraries/PHPExcel/PHPExcel/IOFactory.php +++ b/libraries/PHPExcel/PHPExcel/IOFactory.php @@ -22,28 +22,25 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ +/** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { /** - * @ignore + * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_IWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; - -/** PHPExcel_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - - /** * PHPExcel_IOFactory * @@ -54,9 +51,11 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; class PHPExcel_IOFactory { /** - * Search locations + * Search locations * - * @var array + * @var array + * @access private + * @static */ private static $_searchLocations = array( array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), @@ -64,9 +63,11 @@ class PHPExcel_IOFactory ); /** - * Autoresolve classes + * Autoresolve classes * - * @var array + * @var array + * @access private + * @static */ private static $_autoResolveClasses = array( 'Excel2007', @@ -79,24 +80,28 @@ class PHPExcel_IOFactory ); /** - * Private constructor for PHPExcel_IOFactory + * Private constructor for PHPExcel_IOFactory */ private function __construct() { } /** - * Get search locations + * Get search locations * - * @return array + * @static + * @access public + * @return array */ public static function getSearchLocations() { return self::$_searchLocations; - } + } // function getSearchLocations() /** - * Set search locations + * Set search locations * - * @param array $value - * @throws Exception + * @static + * @access public + * @param array $value + * @throws Exception */ public static function setSearchLocations($value) { if (is_array($value)) { @@ -104,25 +109,30 @@ class PHPExcel_IOFactory } else { throw new Exception('Invalid parameter passed.'); } - } + } // function setSearchLocations() /** - * Add search location + * Add search location * - * @param string $type Example: IWriter - * @param string $location Example: PHPExcel/Writer/{0}.php - * @param string $classname Example: PHPExcel_Writer_{0} + * @static + * @access public + * @param string $type Example: IWriter + * @param string $location Example: PHPExcel/Writer/{0}.php + * @param string $classname Example: PHPExcel_Writer_{0} */ public static function addSearchLocation($type = '', $location = '', $classname = '') { self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); - } + } // function addSearchLocation() /** - * Create PHPExcel_Writer_IWriter + * Create PHPExcel_Writer_IWriter * - * @param PHPExcel $phpExcel - * @param string $writerType Example: Excel2007 - * @return PHPExcel_Writer_IWriter + * @static + * @access public + * @param PHPExcel $phpExcel + * @param string $writerType Example: Excel2007 + * @return PHPExcel_Writer_IWriter + * @throws Exception */ public static function createWriter(PHPExcel $phpExcel, $writerType = '') { // Search type @@ -134,10 +144,6 @@ class PHPExcel_IOFactory $className = str_replace('{0}', $writerType, $searchLocation['class']); $classFile = str_replace('{0}', $writerType, $searchLocation['path']); - if (!class_exists($className)) { - require_once PHPEXCEL_ROOT . $classFile; - } - $instance = new $className($phpExcel); if (!is_null($instance)) { return $instance; @@ -147,13 +153,16 @@ class PHPExcel_IOFactory // Nothing found... throw new Exception("No $searchType found for type $writerType"); - } + } // function createWriter() /** - * Create PHPExcel_Reader_IReader + * Create PHPExcel_Reader_IReader * - * @param string $readerType Example: Excel2007 - * @return PHPExcel_Reader_IReader + * @static + * @access public + * @param string $readerType Example: Excel2007 + * @return PHPExcel_Reader_IReader + * @throws Exception */ public static function createReader($readerType = '') { // Search type @@ -165,10 +174,6 @@ class PHPExcel_IOFactory $className = str_replace('{0}', $readerType, $searchLocation['class']); $classFile = str_replace('{0}', $readerType, $searchLocation['path']); - if (!class_exists($className)) { - require_once PHPEXCEL_ROOT . $classFile; - } - $instance = new $className(); if (!is_null($instance)) { return $instance; @@ -178,24 +183,47 @@ class PHPExcel_IOFactory // Nothing found... throw new Exception("No $searchType found for type $readerType"); - } + } // function createReader() /** - * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution + * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution * - * @param string $pFileName - * @return PHPExcel + * @static + * @access public + * @param string $pFileName + * @return PHPExcel + * @throws Exception */ public static function load($pFilename) { $reader = self::createReaderForFile($pFilename); return $reader->load($pFilename); - } + } // function load() /** - * Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution + * Identify file type using automatic PHPExcel_Reader_IReader resolution * - * @param string $pFileName - * @return PHPExcel_Reader_IReader + * @static + * @access public + * @param string $pFileName + * @return string + * @throws Exception + */ + public static function identify($pFilename) { + $reader = self::createReaderForFile($pFilename); + $className = get_class($reader); + $classType = explode('_',$className); + unset($reader); + return array_pop($classType); + } // function identify() + + /** + * Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFileName + * @return PHPExcel_Reader_IReader + * @throws Exception */ public static function createReaderForFile($pFilename) { @@ -203,41 +231,33 @@ class PHPExcel_IOFactory $pathinfo = pathinfo($pFilename); if (isset($pathinfo['extension'])) { - switch (strtolower($pathinfo['extension'])) { case 'xlsx': $reader = self::createReader('Excel2007'); break; - case 'xls': $reader = self::createReader('Excel5'); break; - case 'ods': $reader = self::createReader('OOCalc'); break; - case 'slk': $reader = self::createReader('SYLK'); break; - case 'xml': $reader = self::createReader('Excel2003XML'); break; - case 'csv': // Do nothing // We must not try to use CSV reader since it loads // all files including Excel files etc. break; - default: break; - } // Let's see if we are lucky - if ($reader->canRead($pFilename)) { + if (isset($reader) && $reader->canRead($pFilename)) { return $reader; } @@ -253,5 +273,5 @@ class PHPExcel_IOFactory } } - } + } // function createReaderForFile() } diff --git a/libraries/PHPExcel/PHPExcel/NamedRange.php b/libraries/PHPExcel/PHPExcel/NamedRange.php index 87054a5f8..af5777b1a 100644 --- a/libraries/PHPExcel/PHPExcel/NamedRange.php +++ b/libraries/PHPExcel/PHPExcel/NamedRange.php @@ -22,28 +22,10 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_ReferenceHelper */ -require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; - - /** * PHPExcel_NamedRange * @@ -81,6 +63,13 @@ class PHPExcel_NamedRange */ private $_localOnly; + /** + * Scope + * + * @var PHPExcel_Worksheet + */ + private $_scope; + /** * Create a new NamedRange * @@ -88,8 +77,9 @@ class PHPExcel_NamedRange * @param PHPExcel_Worksheet $pWorksheet * @param string $pRange * @param bool $pLocalOnly + * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. */ - public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false) + public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) { // Validate data if (is_null($pName) || is_null($pWorksheet)|| is_null($pRange)) { @@ -101,6 +91,8 @@ class PHPExcel_NamedRange $this->_worksheet = $pWorksheet; $this->_range = $pRange; $this->_localOnly = $pLocalOnly; + $this->_scope = ($pLocalOnly == true) ? + (($pScope == null) ? $pWorksheet : $pScope) : null; } /** @@ -201,6 +193,28 @@ class PHPExcel_NamedRange */ public function setLocalOnly($value = false) { $this->_localOnly = $value; + $this->_scope = $value ? $this->_worksheet : null; + return $this; + } + + /** + * Get scope + * + * @return PHPExcel_Worksheet|null + */ + public function getScope() { + return $this->_scope; + } + + /** + * Set scope + * + * @param PHPExcel_Worksheet|null $value + * @return PHPExcel_NamedRange + */ + public function setScope(PHPExcel_Worksheet $value = null) { + $this->_scope = $value; + $this->_localOnly = ($value == null) ? false : true; return $this; } @@ -208,7 +222,7 @@ class PHPExcel_NamedRange * Resolve a named range to a regular cell range * * @param string $pNamedRange Named range - * @param PHPExcel_Worksheet $pSheet Worksheet + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope * @return PHPExcel_NamedRange */ public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) { diff --git a/libraries/PHPExcel/PHPExcel/Reader/CSV.php b/libraries/PHPExcel/PHPExcel/Reader/CSV.php index 8758112fb..5ad6760d0 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/CSV.php +++ b/libraries/PHPExcel/PHPExcel/Reader/CSV.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,24 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - - /** PHPExcel_Reader_DefaultReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; - - /** * PHPExcel_Reader_CSV * @@ -60,49 +51,55 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader { /** - * Input encoding + * Input encoding * - * @var string + * @access private + * @var string */ private $_inputEncoding; /** - * Delimiter + * Delimiter * - * @var string + * @access private + * @var string */ private $_delimiter; /** - * Enclosure + * Enclosure * - * @var string + * @access private + * @var string */ private $_enclosure; /** - * Line ending + * Line ending * - * @var string + * @access private + * @var string */ private $_lineEnding; /** - * Sheet index to read + * Sheet index to read * - * @var int + * @access private + * @var int */ private $_sheetIndex; /** - * PHPExcel_Reader_IReadFilter instance + * PHPExcel_Reader_IReadFilter instance * - * @var PHPExcel_Reader_IReadFilter + * @access private + * @var PHPExcel_Reader_IReadFilter */ private $_readFilter = null; /** - * Create a new PHPExcel_Reader_CSV + * Create a new PHPExcel_Reader_CSV */ public function __construct() { $this->_inputEncoding = 'UTF-8'; @@ -111,15 +108,17 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader $this->_lineEnding = PHP_EOL; $this->_sheetIndex = 0; $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } - + } // function __construct() + /** - * Can the current PHPExcel_Reader_IReader read the file? + * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName - * @return boolean - */ - public function canRead($pFilename) + * @access public + * @param string $pFileName + * @return boolean + * @throws Exception + */ + public function canRead($pFilename) { // Check if file exists if (!file_exists($pFilename)) { @@ -127,13 +126,15 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader } return true; - } + } // function canRead() /** - * Loads PHPExcel from file + * Loads PHPExcel from file * - * @param string $pFilename - * @throws Exception + * @access public + * @param string $pFilename + * @return PHPExcel + * @throws Exception */ public function load($pFilename) { @@ -142,52 +143,60 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Load into this instance return $this->loadIntoExisting($pFilename, $objPHPExcel); - } + } // function load() /** - * Read filter + * Read filter * - * @return PHPExcel_Reader_IReadFilter + * @access public + * @return PHPExcel_Reader_IReadFilter */ public function getReadFilter() { return $this->_readFilter; - } + } // function getReadFilter() /** - * Set read filter + * Set read filter * - * @param PHPExcel_Reader_IReadFilter $pValue + * @access public + * @param PHPExcel_Reader_IReadFilter $pValue */ public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { $this->_readFilter = $pValue; - } + return $this; + } // function setReadFilter() /** - * Set input encoding + * Set input encoding * - * @param string $pValue Input encoding + * @access public + * @param string $pValue Input encoding */ public function setInputEncoding($pValue = 'UTF-8') { $this->_inputEncoding = $pValue; - } + return $this; + } // function setInputEncoding() /** - * Get input encoding + * Get input encoding * - * @return string + * @access public + * @return string */ public function getInputEncoding() { return $this->_inputEncoding; - } + } // function getInputEncoding() /** - * Loads PHPExcel from file into PHPExcel instance + * Loads PHPExcel from file into PHPExcel instance * - * @param string $pFilename - * @param PHPExcel $objPHPExcel - * @throws Exception + * @access public + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { @@ -214,7 +223,6 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader fgets($fileHandle, 4) == "\xEF\xBB\xBF" ? fseek($fileHandle, 3) : fseek($fileHandle, 0); break; - default: break; } @@ -231,16 +239,14 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Unescape enclosures $rowData[$i] = str_replace("\\" . $this->_enclosure, $this->_enclosure, $rowData[$i]); $rowData[$i] = str_replace($this->_enclosure . $this->_enclosure, $this->_enclosure, $rowData[$i]); - + // Convert encoding if necessary if ($this->_inputEncoding !== 'UTF-8') { $rowData[$i] = PHPExcel_Shared_String::ConvertEncoding($rowData[$i], 'UTF-8', $this->_inputEncoding); } // Set cell value - $objPHPExcel->getActiveSheet()->setCellValue( - $columnLetter . $currentRow, $rowData[$i] - ); + $objPHPExcel->getActiveSheet()->getCell($columnLetter . $currentRow)->setValue($rowData[$i]); } } } @@ -250,42 +256,46 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Return return $objPHPExcel; - } + } // function loadIntoExisting() /** - * Get delimiter + * Get delimiter * - * @return string + * @access public + * @return string */ public function getDelimiter() { return $this->_delimiter; - } + } // function getDelimiter() /** - * Set delimiter + * Set delimiter * - * @param string $pValue Delimiter, defaults to , - * @return PHPExcel_Reader_CSV + * @access public + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Reader_CSV */ public function setDelimiter($pValue = ',') { $this->_delimiter = $pValue; return $this; - } + } // function setDelimiter() /** - * Get enclosure + * Get enclosure * - * @return string + * @access public + * @return string */ public function getEnclosure() { return $this->_enclosure; - } + } // function getEnclosure() /** - * Set enclosure + * Set enclosure * - * @param string $pValue Enclosure, defaults to " - * @return PHPExcel_Reader_CSV + * @access public + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Reader_CSV */ public function setEnclosure($pValue = '"') { if ($pValue == '') { @@ -293,45 +303,49 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader } $this->_enclosure = $pValue; return $this; - } + } // function setEnclosure() /** - * Get line ending + * Get line ending * - * @return string + * @access public + * @return string */ public function getLineEnding() { return $this->_lineEnding; - } + } // function getLineEnding() /** - * Set line ending + * Set line ending * - * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) - * @return PHPExcel_Reader_CSV + * @access public + * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) + * @return PHPExcel_Reader_CSV */ public function setLineEnding($pValue = PHP_EOL) { $this->_lineEnding = $pValue; return $this; - } + } // function setLineEnding() /** - * Get sheet index + * Get sheet index * - * @return int + * @access public + * @return int */ public function getSheetIndex() { return $this->_sheetIndex; - } + } // function getSheetIndex() /** - * Set sheet index + * Set sheet index * - * @param int $pValue Sheet index - * @return PHPExcel_Reader_CSV + * @access public + * @param int $pValue Sheet index + * @return PHPExcel_Reader_CSV */ public function setSheetIndex($pValue = 0) { $this->_sheetIndex = $pValue; return $this; - } + } // function setSheetIndex() } diff --git a/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php b/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php index 63c5ae3cc..bfb6af596 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php +++ b/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,12 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel_Reader_IReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReadFilter.php'; - - /** * PHPExcel_Reader_DefaultReadFilter * @@ -54,7 +57,7 @@ class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter * @param $row Row index * @param $worksheetName Optional worksheet name * @return boolean - */ + */ public function readCell($column, $row, $worksheetName = '') { return true; } diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php b/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php index 89d5a83c3..ee22d7cbf 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,27 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Calculation */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; - - /** PHPExcel_Reader_DefaultReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; - - /** * PHPExcel_Reader_Excel2003XML * @@ -236,6 +224,7 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader * Loads PHPExcel from file * * @param string $pFilename + * @return PHPExcel * @throws Exception */ public function load($pFilename) @@ -288,6 +277,7 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader * * @param string $pFilename * @param PHPExcel $objPHPExcel + * @return PHPExcel * @throws Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) @@ -508,7 +498,7 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader $objPHPExcel->createSheet(); $objPHPExcel->setActiveSheetIndex($worksheetID); if (isset($worksheet_ss['Name'])) { - $worksheetName = $worksheet_ss['Name']; + $worksheetName = (string) $worksheet_ss['Name']; $objPHPExcel->getActiveSheet()->setTitle($worksheetName); } @@ -660,7 +650,7 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader // print_r($this->_styles[$style]); // echo '
'; if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { - $objPHPExcel->getActiveSheet()->setCellValue($columnID.$rowID,NULL); + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(NULL); } $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->_styles[$style]); } diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php b/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php index 6cbc89372..6d3922cc1 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,63 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Style */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; - -/** PHPExcel_Style_Borders */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php'; - -/** PHPExcel_Style_Conditional */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Conditional.php'; - -/** PHPExcel_Style_Protection */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php'; - -/** PHPExcel_Style_NumberFormat */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; - -/** PHPExcel_Worksheet_BaseDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php'; - -/** PHPExcel_Worksheet_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; - -/** PHPExcel_Shared_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Shared_File */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_ReferenceHelper */ -require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; - - /** PHPExcel_Reader_IReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReadFilter.php'; - - /** PHPExcel_Reader_DefaultReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; - - /** * PHPExcel_Reader_Excel2007 * @@ -298,7 +250,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + public function _getFromZipArchive(ZipArchive $archive, $fileName = '') { // Root-relative paths @@ -307,14 +259,14 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $fileName = substr($fileName, strpos($fileName, '//') + 1); } $fileName = PHPExcel_Shared_File::realpath($fileName); - + // Apache POI fixes $contents = $archive->getFromName($fileName); if ($contents === false) { $contents = $archive->getFromName(substr($fileName, 1)); } - + /* if (strpos($contents, '_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); - + // normal style, currently not using it for anything } } @@ -498,7 +450,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - + // Set base date if ($xmlWorkbook->workbookPr) { PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); @@ -519,66 +471,70 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader { foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { ++$oldSheetId; - + // Check if sheet should be skipped if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { ++$countSkippedSheets; $mapSheetId[$oldSheetId] = null; continue; } - + // Map old sheet id in original workbook to new sheet id. // They will differ if loadSheetsOnly() is being used $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; - + // Load sheet $docSheet = $excel->createSheet(); $docSheet->setTitle((string) $eleSheet["name"]); $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - + $sharedFormulas = array(); - + if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { $docSheet->setSheetState( (string) $eleSheet["state"] ); } - + if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); } - + if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); } - + if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false); } - + + if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) { + $docSheet->setShowRowColHeaders((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'] ? true : false); + } + if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false); } - + if (isset($xmlSheet->sheetViews->sheetView->pane)) { if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); } else { $xSplit = 0; $ySplit = 0; - + if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); } - + if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); } - + $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); } } - + if (isset($xmlSheet->sheetViews->sheetView->selection)) { if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; @@ -587,29 +543,29 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->setSelectedCells($sqref); } } - + } - + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); } } - + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) { $docSheet->setShowSummaryRight(false); } else { $docSheet->setShowSummaryRight(true); } - + if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) { $docSheet->setShowSummaryBelow(false); } else { $docSheet->setShowSummaryBelow(true); } } - + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && $xmlSheet->sheetPr->pageSetUpPr['fitToPage'] == false) { $docSheet->getPageSetup()->setFitToPage(false); @@ -617,7 +573,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->getPageSetup()->setFitToPage(true); } } - + if (isset($xmlSheet->sheetFormatPr)) { if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); @@ -626,15 +582,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); } } - + if (isset($xmlSheet->cols) && !$this->_readDataOnly) { foreach ($xmlSheet->cols->col as $col) { for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { - if ($col["style"]) { + if ($col["style"] && !$this->_readDataOnly) { $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); } if ($col["bestFit"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); + //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); } if ($col["hidden"]) { $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); @@ -646,23 +602,23 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); } $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); - + if (intval($col["max"]) == 16384) { break; } } } } - + if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') { $docSheet->setShowGridlines(true); } - + if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') { $docSheet->setPrintGridlines(true); } - + if ($xmlSheet->printOptions['horizontalCentered']) { $docSheet->getPageSetup()->setHorizontalCentered(true); } @@ -670,7 +626,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->getPageSetup()->setVerticalCentered(true); } } - + if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { foreach ($xmlSheet->sheetData->row as $row) { if ($row["ht"] && !$this->_readDataOnly) { @@ -685,25 +641,25 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if ($row["outlineLevel"] > 0) { $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); } - if ($row["s"]) { + if ($row["s"] && !$this->_readDataOnly) { $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); } - + foreach ($row->c as $c) { $r = (string) $c["r"]; $cellDataType = (string) $c["t"]; $value = null; $calculatedValue = null; - + // Read cell? if (!is_null($this->getReadFilter())) { $coordinates = PHPExcel_Cell::coordinateFromString($r); - + if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { continue; } } - + // echo 'Reading cell '.$coordinates[0].$coordinates[1].'
'; // print_r($c); // echo '
'; @@ -715,14 +671,14 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader // echo 'String
'; if ((string)$c->v != '') { $value = $sharedStrings[intval($c->v)]; - + if ($value instanceof PHPExcel_RichText) { $value = clone $value; } } else { $value = ''; } - + break; case "b": // echo 'Boolean
'; @@ -737,7 +693,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader case "inlineStr": // echo 'Inline String
'; $value = $this->_parseRichText($c->is); - + break; case "e": // echo 'Error
'; @@ -748,9 +704,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); // echo '$calculatedValue = '.$calculatedValue.'
'; } - + break; - + default: // echo 'Default
'; if (!isset($c->f)) { @@ -762,48 +718,44 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); // echo '$calculatedValue = '.$calculatedValue.'
'; } - + break; } // echo 'Value is '.$value.'
'; - + // Check for numeric values if (is_numeric($value) && $cellDataType != 's') { if ($value == (int)$value) $value = (int)$value; elseif ($value == (float)$value) $value = (float)$value; elseif ($value == (double)$value) $value = (double)$value; } - + // Rich text? if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { $value = $value->getPlainText(); } - + + $cell = $docSheet->getCell($r); // Assign value if ($cellDataType != '') { - $docSheet->setCellValueExplicit($r, $value, $cellDataType); + $cell->setValueExplicit($value, $cellDataType); } else { - $docSheet->setCellValue($r, $value); + $cell->setValue($value); } if (!is_null($calculatedValue)) { - $docSheet->getCell($r)->setCalculatedValue($calculatedValue); + $cell->setCalculatedValue($calculatedValue); } - + // Style information? if ($c["s"] && !$this->_readDataOnly) { // no style index means 0, it seems - $docSheet->getCell($r)->setXfIndex(isset($styles[intval($c["s"])]) ? + $cell->setXfIndex(isset($styles[intval($c["s"])]) ? intval($c["s"]) : 0); } - - // Set rich text parent - if ($value instanceof PHPExcel_RichText && !$this->_readDataOnly) { - $value->setParent($docSheet->getCell($r)); - } } } } - + $conditionals = array(); if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { foreach ($xmlSheet->conditionalFormatting as $conditional) { @@ -812,14 +764,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader ( (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_EXPRESSION ) && isset($dxfs[intval($cfRule["dxfId"])]) ) { $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; } } } - + foreach ($conditionals as $ref => $cfRules) { ksort($cfRules); $conditionalStyles = array(); @@ -827,11 +780,11 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objConditional = new PHPExcel_Style_Conditional(); $objConditional->setConditionType((string)$cfRule["type"]); $objConditional->setOperatorType((string)$cfRule["operator"]); - + if ((string)$cfRule["text"] != '') { $objConditional->setText((string)$cfRule["text"]); } - + if (count($cfRule->formula) > 1) { foreach ($cfRule->formula as $formula) { $objConditional->addCondition((string)$formula); @@ -842,7 +795,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); $conditionalStyles[] = $objConditional; } - + // Extract all cell references in $ref $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); foreach ($aReferences as $reference) { @@ -850,7 +803,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { foreach ($aKeys as $key) { @@ -858,7 +811,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true"); } } - + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); if ($xmlSheet->protectedRanges->protectedRange) { @@ -867,17 +820,17 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { $docSheet->setAutoFilter((string) $xmlSheet->autoFilter["ref"]); } - + if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { $docSheet->mergeCells((string) $mergeCell["ref"]); } } - + if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { $docPageMargins = $docSheet->getPageMargins(); $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); @@ -887,10 +840,10 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); } - + if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { $docPageSetup = $docSheet->getPageSetup(); - + if (isset($xmlSheet->pageSetup["orientation"])) { $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); } @@ -911,10 +864,10 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); } } - + if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { $docHeaderFooter = $docSheet->getHeaderFooter(); - + if (isset($xmlSheet->headerFooter["differentOddEven"]) && ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) { $docHeaderFooter->setDifferentOddEven(true); @@ -939,7 +892,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } else { $docHeaderFooter->setAlignWithMargins(true); } - + $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); @@ -947,7 +900,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); } - + if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { foreach ($xmlSheet->rowBreaks->brk as $brk) { if ($brk["man"]) { @@ -962,34 +915,38 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { // Uppercase coordinate $range = strtoupper($dataValidation["sqref"]); - - // Extract all cell references in $range - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($range); - foreach ($aReferences as $reference) { - // Create validation - $docValidation = $docSheet->getCell($reference)->getDataValidation(); - $docValidation->setType((string) $dataValidation["type"]); - $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); - $docValidation->setOperator((string) $dataValidation["operator"]); - $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); - $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); - $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); - $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); - $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); - $docValidation->setError((string) $dataValidation["error"]); - $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); - $docValidation->setPrompt((string) $dataValidation["prompt"]); - $docValidation->setFormula1((string) $dataValidation->formula1); - $docValidation->setFormula2((string) $dataValidation->formula2); + $rangeSet = explode(' ',$range); + foreach($rangeSet as $range) { + $stRange = $docSheet->shrinkRangeToFit($range); + + // Extract all cell references in $range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); + foreach ($aReferences as $reference) { + // Create validation + $docValidation = $docSheet->getCell($reference)->getDataValidation(); + $docValidation->setType((string) $dataValidation["type"]); + $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); + $docValidation->setOperator((string) $dataValidation["operator"]); + $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); + $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); + $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); + $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); + $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); + $docValidation->setError((string) $dataValidation["error"]); + $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); + $docValidation->setPrompt((string) $dataValidation["prompt"]); + $docValidation->setFormula1((string) $dataValidation->formula1); + $docValidation->setFormula2((string) $dataValidation->formula2); + } } } } - + // Add hyperlinks $hyperlinks = array(); if (!$this->_readDataOnly) { @@ -1002,30 +959,31 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + // Loop through hyperlinks if ($xmlSheet && $xmlSheet->hyperlinks) { foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { // Link url $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { + $cell = $docSheet->getCell( $cellReference ); if (isset($linkRel['id'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); + $cell->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); } if (isset($hyperlink['location'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); + $cell->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); } - + // Tooltip if (isset($hyperlink['tooltip'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); + $cell->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); } } } } } - + // Add comments $comments = array(); $vmlComments = array(); @@ -1042,92 +1000,92 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + // Loop through comments foreach ($comments as $relName => $relPath) { // Load comments file $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); $commentsFile = simplexml_load_string($this->_getFromZipArchive($zip, $relPath) ); - + // Utility variables $authors = array(); - + // Loop through authors foreach ($commentsFile->authors->author as $author) { $authors[] = (string)$author; } - + // Loop through contents foreach ($commentsFile->commentList->comment as $comment) { $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); } } - + // Loop through VML comments foreach ($vmlComments as $relName => $relPath) { // Load VML comments file $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); $vmlCommentsFile = simplexml_load_string( $this->_getFromZipArchive($zip, $relPath) ); $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - + $shapes = $vmlCommentsFile->xpath('//v:shape'); foreach ($shapes as $shape) { $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - + if (isset($shape['style'])) { $style = (string)$shape['style']; $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); $column = null; $row = null; - + $clientData = $shape->xpath('.//x:ClientData'); - if (is_array($clientData)) { + if (is_array($clientData) && count($clientData) > 0) { $clientData = $clientData[0]; - + if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { $temp = $clientData->xpath('.//x:Row'); if (is_array($temp)) $row = $temp[0]; - + $temp = $clientData->xpath('.//x:Column'); if (is_array($temp)) $column = $temp[0]; } } - + if (!is_null($column) && !is_null($row)) { // Set comment properties $comment = $docSheet->getCommentByColumnAndRow($column, $row + 1); $comment->getFillColor()->setRGB( $fillColor ); - + // Parse style $styleArray = explode(';', str_replace(' ', '', $style)); foreach ($styleArray as $stylePair) { $stylePair = explode(':', $stylePair); - + if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); - + } } } } } - + // Header/footer images if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $vmlRelationship = ''; - + foreach ($relsWorksheet->Relationship as $ele) { if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); } } - + if ($vmlRelationship != '') { // Fetch linked images $relsVML = simplexml_load_string($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); @@ -1137,27 +1095,27 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); } } - + // Fetch VML document $vmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $vmlRelationship)); $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - + $hfImages = array(); - + $shapes = $vmlDrawing->xpath('//v:shape'); foreach ($shapes as $shape) { $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); $imageData = $shape->xpath('//v:imagedata'); $imageData = $imageData[0]; - + $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); $style = self::toCSSArray( (string)$shape['style'] ); - + $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); if (isset($imageData['title'])) { $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); } - + $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false); $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); @@ -1166,14 +1124,14 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); } - + $docSheet->getHeaderFooter()->setImages($hfImages); } } } - + } - + // TODO: Make sure drawings and graph are loaded differently! if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); @@ -1188,7 +1146,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; $relsDrawing = simplexml_load_string($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $images = array(); - + if ($relsDrawing && $relsDrawing->Relationship) { foreach ($relsDrawing->Relationship as $ele) { if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { @@ -1197,7 +1155,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); - + if ($xmlDrawing->oneCellAnchor) { foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { if ($oneCellAnchor->pic->blipFill) { @@ -1245,10 +1203,10 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); $objDrawing->setResizeProportional(false); - + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); - + if ($xfrm) { $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); } @@ -1266,11 +1224,11 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + } } } - + // Loop through definedNames if ($xmlWorkbook->definedNames) { foreach ($xmlWorkbook->definedNames->definedName as $definedName) { @@ -1278,94 +1236,119 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $extractedRange = (string)$definedName; $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); $extractedRange = str_replace('$', '', $extractedRange); - + // Valid range? if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { continue; } - + // Some definedNames are only applicable if we are on the same sheet... if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { // Switch on type switch ((string)$definedName['name']) { - + case '_xlnm._FilterDatabase': $docSheet->setAutoFilter($extractedRange); break; - + case '_xlnm.Print_Titles': // Split $extractedRange $extractedRange = explode(',', $extractedRange); - + // Set print titles - if (isset($extractedRange[0])) { - $range = explode(':', $extractedRange[0]); - - if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') - $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); - $range[0] = str_replace('$', '', $range[0]); - if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') - $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); - $range[1] = str_replace('$', '', $range[1]); - - $docSheet->getPageSetup()->setColumnsToRepeatAtLeft( $range ); + foreach ($extractedRange as $range) { + $matches = array(); + + // check for repeating columns, e g. 'A:A' or 'A:D' + if (preg_match('/^([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2])); + } + // check for repeating rows, e.g. '1:1' or '1:5' + elseif (preg_match('/^(\d+)\:(\d+)$/', $range, $matches)) { + $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2])); + } } - if (isset($extractedRange[1])) { - $range = explode(':', $extractedRange[1]); - - if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') - $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); - $range[0] = str_replace('$', '', $range[0]); - if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') - $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); - $range[1] = str_replace('$', '', $range[1]); - - $docSheet->getPageSetup()->setRowsToRepeatAtTop( $range ); - } - break; - + case '_xlnm.Print_Area': $range = explode('!', $extractedRange); $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - + $docSheet->getPageSetup()->setPrintArea($extractedRange); break; - + default: - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, true) ); break; } - } else { - // "Global" definedNames - $locatedSheet = null; - $extractedSheetName = ''; - if (strpos( (string)$definedName, '!' ) !== false) { - // Extract sheet name - $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); - $extractedSheetName = $extractedSheetName[0]; - - // Locate sheet - $locatedSheet = $excel->getSheetByName($extractedSheetName); - - // Modify range - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - } - - if (!is_null($locatedSheet)) { - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); - } } } } - + // Next sheet id ++$sheetId; } + + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + $extractedRange = str_replace('$', '', $extractedRange); + + // Valid range? + if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { + continue; + } + + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '') { + // Local defined name + // Switch on type + switch ((string)$definedName['name']) { + + case '_xlnm._FilterDatabase': + case '_xlnm.Print_Titles': + case '_xlnm.Print_Area': + break; + + default: + $range = explode('!', (string)$definedName); + if (count($range) == 2) { + $range[0] = str_replace("''", "'", $range[0]); + $range[0] = str_replace("'", "", $range[0]); + if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $scope = $docSheet->getParent()->getSheet((string)$definedName['localSheetId']); + + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + } + } + break; + } + } else if (!isset($definedName['localSheetId'])) { + // "Global" definedNames + $locatedSheet = null; + $extractedSheetName = ''; + if (strpos( (string)$definedName, '!' ) !== false) { + // Extract sheet name + $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); + $extractedSheetName = $extractedSheetName[0]; + + // Locate sheet + $locatedSheet = $excel->getSheetByName($extractedSheetName); + + // Modify range + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + } + + if (!is_null($locatedSheet)) { + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + } + } + } + } } if (!$this->_readDataOnly) { @@ -1410,13 +1393,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docStyle->getFont()->setName((string) $style->font->name["val"]); $docStyle->getFont()->setSize((string) $style->font->sz["val"]); if (isset($style->font->b)) { - $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || $style->font->b["val"] == 'true'); + $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || $style->font->b["val"] == 'true' || $style->font->b["val"] == '1'); } if (isset($style->font->i)) { - $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || $style->font->i["val"] == 'true'); + $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || $style->font->i["val"] == 'true' || $style->font->i["val"] == '1'); } if (isset($style->font->strike)) { - $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || $style->font->strike["val"] == 'true'); + $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || $style->font->strike["val"] == 'true' || $style->font->strike["val"] == '1'); } $docStyle->getFont()->getColor()->setARGB($this->_readColor($style->font->color)); @@ -1540,9 +1523,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $is->t ) ); } else { foreach ($is->r as $run) { - $objText = $value->createTextRun( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + if (!isset($run->rPr)) { + $objText = $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + + } else { + $objText = $value->createTextRun( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); - if (isset($run->rPr)) { if (isset($run->rPr->rFont["val"])) { $objText->getFont()->setName((string) $run->rPr->rFont["val"]); } diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel5.php b/libraries/PHPExcel/PHPExcel/Reader/Excel5.php index 8509b0801..1002749b9 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel5.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ // Original file header of ParseXL (used as the base for this class): @@ -63,54 +63,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Reader_Excel5_Escher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/Excel5/Escher.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Shared_Excel5 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Excel5.php'; - -/** PHPExcel_Shared_Escher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php'; - -/** PHPExcel_Shared_OLERead */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLERead.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_NamedRange */ -require_once PHPEXCEL_ROOT . 'PHPExcel/NamedRange.php'; - -/** PHPExcel_Reader_IReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReadFilter.php'; - -/** PHPExcel_Reader_DefaultReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; - -/** PHPExcel_Worksheet_MemoryDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; - -/** PHPExcel_Style_Borders */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php'; - - /** * PHPExcel_Reader_Excel5 * @@ -144,6 +105,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_NOTE = 0x001c; const XLS_Type_SELECTION = 0x001d; const XLS_Type_DATEMODE = 0x0022; + const XLS_Type_EXTERNNAME = 0x0023; const XLS_Type_LEFTMARGIN = 0x0026; const XLS_Type_RIGHTMARGIN = 0x0027; const XLS_Type_TOPMARGIN = 0x0028; @@ -176,8 +138,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_LABELSST = 0x00fd; const XLS_Type_EXTSST = 0x00ff; const XLS_Type_EXTERNALBOOK = 0x01ae; + const XLS_Type_DATAVALIDATIONS = 0x01b2; const XLS_Type_TXO = 0x01b6; const XLS_Type_HYPERLINK = 0x01b8; + const XLS_Type_DATAVALIDATION = 0x01be; const XLS_Type_DIMENSION = 0x0200; const XLS_Type_BLANK = 0x0201; const XLS_Type_NUMBER = 0x0203; @@ -222,14 +186,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private $_readFilter = null; /** - * OLE reader + * Summary Information stream data. * - * @var PHPExcel_Shared_OLERead + * @var string */ - private $_ole; + private $_summaryInformation; /** - * Stream data that is read. Includes workbook globals substream as well as sheet substreams + * Workbook stream data. (Includes workbook globals substream as well as sheet substreams) * * @var string */ @@ -320,6 +284,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader */ private $_ref; + /** + * External names + * + * @var array + */ + private $_externalNames; + /** * Defined names * @@ -503,10 +474,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader try { // Use ParseXL for the hard work. - $this->_ole = new PHPExcel_Shared_OLERead(); + $ole = new PHPExcel_Shared_OLERead(); // get excel data - $res = $this->_ole->read($pFilename); + $res = $ole->read($pFilename); return true; } catch (Exception $e) { @@ -518,10 +489,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * Loads PHPExcel from file * * @param string $pFilename + * @return PHPExcel * @throws Exception */ public function load($pFilename) { + // Read the OLE file + $this->_loadOLE($pFilename); + // Initialisations $this->_phpExcel = new PHPExcel; $this->_phpExcel->removeSheetByIndex(0); // remove 1st sheet @@ -530,12 +505,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $this->_phpExcel->removeCellXfByIndex(0); // remove the default style } - // Use ParseXL for the hard work. - $this->_ole = new PHPExcel_Shared_OLERead(); - - // get excel data - $res = $this->_ole->read($pFilename); - $this->_data = $this->_ole->getWorkBook(); + // Read the summary information stream (containing meta data) + $this->_readSummaryInformation(); // total byte size of Excel data (workbook global substream + sheet substreams) $this->_dataSize = strlen($this->_data); @@ -561,26 +532,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $code = $this->_GetInt2d($this->_data, $this->_pos); switch ($code) { - case self::XLS_Type_BOF: - $pos = $this->_pos; - $length = $this->_GetInt2d($this->_data, $pos + 2); - $recordData = substr($this->_data, $pos + 4, $length); - - // offset: 0; size: 2; BIFF version - $this->_version = $this->_GetInt2d($this->_data, $pos + 4); - - if (($this->_version != self::XLS_BIFF8) && ($this->_version != self::XLS_BIFF7)) { - return false; - } - - // offset: 2; size: 2; type of stream - $substreamType = $this->_GetInt2d($this->_data, $pos + 6); - if ($substreamType != self::XLS_WorkbookGlobals) { - return false; - } - $this->_pos += 4 + $length; - break; - + case self::XLS_Type_BOF: $this->_readBof(); break; case self::XLS_Type_FILEPASS: $this->_readFilepass(); break; case self::XLS_Type_CODEPAGE: $this->_readCodepage(); break; case self::XLS_Type_DATEMODE: $this->_readDateMode(); break; @@ -592,6 +544,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_PALETTE: $this->_readPalette(); break; case self::XLS_Type_SHEET: $this->_readSheet(); break; case self::XLS_Type_EXTERNALBOOK: $this->_readExternalBook(); break; + case self::XLS_Type_EXTERNNAME: $this->_readExternName(); break; case self::XLS_Type_EXTERNSHEET: $this->_readExternSheet(); break; case self::XLS_Type_DEFINEDNAME: $this->_readDefinedName(); break; case self::XLS_Type_MSODRAWINGGROUP: $this->_readMsoDrawingGroup(); break; @@ -673,6 +626,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Parse the individual sheets foreach ($this->_sheets as $sheet) { + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module + continue; + } + // check if sheet should be skipped if (isset($this->_loadSheetsOnly) && !in_array($sheet['name'], $this->_loadSheetsOnly)) { continue; @@ -700,27 +658,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Initialize shared formulas $this->_sharedFormulas = array(); - while ($this->_pos < $this->_dataSize) { + while ($this->_pos <= $this->_dataSize - 4) { $code = $this->_GetInt2d($this->_data, $this->_pos); switch ($code) { - case self::XLS_Type_BOF: - $length = $this->_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); - - // move stream pointer to next record - $this->_pos += 4 + $length; - - // do not use this version information for anything - // it is unreliable (OpenOffice doc, 5.8), use only version information from the global stream - - // offset: 2; size: 2; type of the following data - $substreamType = $this->_GetInt2d($recordData, 2); - if ($substreamType != self::XLS_Worksheet) { - break 2; - } - break; - + case self::XLS_Type_BOF: $this->_readBof(); break; case self::XLS_Type_PRINTGRIDLINES: $this->_readPrintGridlines(); break; case self::XLS_Type_DEFAULTROWHEIGHT: $this->_readDefaultRowHeight(); break; case self::XLS_Type_SHEETPR: $this->_readSheetPr(); break; @@ -762,6 +704,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_SELECTION: $this->_readSelection(); break; case self::XLS_Type_MERGEDCELLS: $this->_readMergedCells(); break; case self::XLS_Type_HYPERLINK: $this->_readHyperLink(); break; + case self::XLS_Type_DATAVALIDATIONS: $this->_readDataValidations(); break; + case self::XLS_Type_DATAVALIDATION: $this->_readDataValidation(); break; case self::XLS_Type_SHEETLAYOUT: $this->_readSheetLayout(); break; case self::XLS_Type_SHEETPROTECTION: $this->_readSheetProtection(); break; case self::XLS_Type_RANGEPROTECTION: $this->_readRangeProtection(); break; @@ -957,7 +901,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $extractedRange = $explodes[1]; $extractedRange = str_replace('$', '', $extractedRange); - $this->_phpExcel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, false) ); + $localOnly = ($definedName['scope'] == 0) ? false : true; + $scope = ($definedName['scope'] == 0) ? + null : $this->_phpExcel->getSheetByName($this->_sheets[$definedName['scope'] - 1]['name']); + + $this->_phpExcel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, $localOnly, $scope) ); } } } @@ -966,6 +914,148 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader return $this->_phpExcel; } + /** + * Use OLE reader to extract the relevant data streams from the OLE file + * + * @param string $pFilename + */ + private function _loadOLE($pFilename) + { + // OLE reader + $ole = new PHPExcel_Shared_OLERead(); + + // get excel data + $res = $ole->read($pFilename); + $this->_data = $ole->getWorkBook(); + + // Get summary information data + $this->_summaryInformation = $ole->getSummaryInformation(); + } + + /** + * Read summary information + */ + private function _readSummaryInformation() + { + if (!isset($this->_summaryInformation)) { + return; + } + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + // offset: 2; size: 2; + // offset: 4; size: 2; OS version + // offset: 6; size: 2; OS indicator + // offset: 8; size: 16 + // offset: 24; size: 4; section count + + // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 + // offset: 44; size: 4 + + // section header + // offset: 48; size: 4; section length + $secLength = $this->_GetInt4d($this->_summaryInformation, 48); + + // offset: 52; size: 4; property count + $countProperties = $this->_GetInt4d($this->_summaryInformation, 52); + + // initialize code page (used to resolve string values) + $codePage = 'CP1252'; + + // offset: 56; size: var + // loop through property decarations and properties + for ($i = 0; $i < $countProperties; ++$i) { + + // offset: 56 + 8 * $i; size: 4; property ID + $id = $this->_GetInt4d($this->_summaryInformation, 56 + 8 * $i); + + // offset: 60 + 8 * $i; size: 4; offset from beginning of section (48) + $offset = $this->_GetInt4d($this->_summaryInformation, 60 + 8 * $i); + + $type = $this->_GetInt4d($this->_summaryInformation, 48 + $offset); + + // initialize property value + $value = null; + + // extract property value based on property type + switch ($type) { + case 0x02: // 2 byte signed integer + $value = $this->_GetInt2d($this->_summaryInformation, 52 + $offset); + break; + + case 0x03: // 4 byte signed integer + $value = $this->_GetInt4d($this->_summaryInformation, 52 + $offset); + break; + + case 0x13: // 4 byte unsigned integer + // not needed yet, fix later if necessary + break; + + case 0x1E: // null-terminated string prepended by dword string length + $byteLength = $this->_GetInt4d($this->_summaryInformation, 52 + $offset); + $value = substr($this->_summaryInformation, 56 + $offset, $byteLength); + $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); + $value = rtrim($value); + break; + + case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + // PHP-time + $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_summaryInformation, 52 + $offset, 8)); + break; + + case 0x47: // Clipboard format + // not needed yet, fix later if necessary + break; + } + + // Use value of property id as appropriate + switch ($id) { + case 0x01: // Code Page + $codePage = PHPExcel_Shared_CodePage::NumberToName($value); + break; + + case 0x02: // Title + $this->_phpExcel->getProperties()->setTitle($value); + break; + + case 0x03: // Subject + $this->_phpExcel->getProperties()->setSubject($value); + break; + + case 0x04: // Author (Creator) + $this->_phpExcel->getProperties()->setCreator($value); + break; + + case 0x05: // Keywords + $this->_phpExcel->getProperties()->setKeywords($value); + break; + + case 0x06: // Comments (Description) + $this->_phpExcel->getProperties()->setDescription($value); + break; + + case 0x08: // Last Saved By (LastModifiedBy) + $this->_phpExcel->getProperties()->setLastModifiedBy($value); + break; + + case 0x09: // Revision + // not supported by PHPExcel + break; + + case 0x0C: // Created + $this->_phpExcel->getProperties()->setCreated($value); + break; + + case 0x0D: // Modified + $this->_phpExcel->getProperties()->setModified($value); + break; + + case 0x12: // Name of creating application + // not supported by PHPExcel + break; + } + } + } + /** * Reads a general type of BIFF record. Does nothing except for moving stream pointer forward to next record. */ @@ -978,6 +1068,45 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $this->_pos += 4 + $length; } + /** + * Read BOF + */ + private function _readBof() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 2; size: 2; type of the following data + $substreamType = $this->_GetInt2d($recordData, 2); + + switch ($substreamType) { + case self::XLS_WorkbookGlobals: + $version = $this->_GetInt2d($recordData, 0); + if (($version != self::XLS_BIFF8) && ($version != self::XLS_BIFF7)) { + throw new Exception('Cannot read this Excel file. Version is too old.'); + } + $this->_version = $version; + break; + + case self::XLS_Worksheet: + // do not use this version information for anything + // it is unreliable (OpenOffice doc, 5.8), use only version information from the global stream + break; + + default: + // substream, e.g. chart + // just skip the entire substream + do { + $code = $this->_GetInt2d($this->_data, $this->_pos); + $this->_readDefault(); + } while ($code != self::XLS_Type_EOF && $this->_pos < $this->_dataSize); + break; + } + } + /** * FILEPASS * @@ -1020,159 +1149,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 0; size: 2; code page identifier $codepage = $this->_GetInt2d($recordData, 0); - switch ($codepage) { - - case 367: // ASCII - $this->_codepage ="ASCII"; - break; - - case 437: //OEM US - $this->_codepage ="CP437"; - break; - - case 720: //OEM Arabic - // currently not supported by libiconv - $this->_codepage = ""; - break; - - case 737: //OEM Greek - $this->_codepage ="CP737"; - break; - - case 775: //OEM Baltic - $this->_codepage ="CP775"; - break; - - case 850: //OEM Latin I - $this->_codepage ="CP850"; - break; - - case 852: //OEM Latin II (Central European) - $this->_codepage ="CP852"; - break; - - case 855: //OEM Cyrillic - $this->_codepage ="CP855"; - break; - - case 857: //OEM Turkish - $this->_codepage ="CP857"; - break; - - case 858: //OEM Multilingual Latin I with Euro - $this->_codepage ="CP858"; - break; - - case 860: //OEM Portugese - $this->_codepage ="CP860"; - break; - - case 861: //OEM Icelandic - $this->_codepage ="CP861"; - break; - - case 862: //OEM Hebrew - $this->_codepage ="CP862"; - break; - - case 863: //OEM Canadian (French) - $this->_codepage ="CP863"; - break; - - case 864: //OEM Arabic - $this->_codepage ="CP864"; - break; - - case 865: //OEM Nordic - $this->_codepage ="CP865"; - break; - - case 866: //OEM Cyrillic (Russian) - $this->_codepage ="CP866"; - break; - - case 869: //OEM Greek (Modern) - $this->_codepage ="CP869"; - break; - - case 874: //ANSI Thai - $this->_codepage ="CP874"; - break; - - case 932: //ANSI Japanese Shift-JIS - $this->_codepage ="CP932"; - break; - - case 936: //ANSI Chinese Simplified GBK - $this->_codepage ="CP936"; - break; - - case 949: //ANSI Korean (Wansung) - $this->_codepage ="CP949"; - break; - - case 950: //ANSI Chinese Traditional BIG5 - $this->_codepage ="CP950"; - break; - - case 1200: //UTF-16 (BIFF8) - $this->_codepage ="UTF-16LE"; - break; - - case 1250:// ANSI Latin II (Central European) - $this->_codepage ="CP1250"; - break; - - case 1251: //ANSI Cyrillic - $this->_codepage ="CP1251"; - break; - - case 1252: //ANSI Latin I (BIFF4-BIFF7) - $this->_codepage ="CP1252"; - break; - - case 1253: //ANSI Greek - $this->_codepage ="CP1253"; - break; - - case 1254: //ANSI Turkish - $this->_codepage ="CP1254"; - break; - - case 1255: //ANSI Hebrew - $this->_codepage ="CP1255"; - break; - - case 1256: //ANSI Arabic - $this->_codepage ="CP1256"; - break; - - case 1257: //ANSI Baltic - $this->_codepage ="CP1257"; - break; - - case 1258: //ANSI Vietnamese - $this->_codepage ="CP1258"; - break; - - case 1361: //ANSI Korean (Johab) - $this->_codepage ="CP1361"; - break; - - case 10000: //Apple Roman - $this->_codepage = 'MAC'; - break; - - case 32768: //Apple Roman - $this->_codepage = 'MAC'; - break; - - case 32769: //ANSI Latin I (BIFF2-BIFF3) - // currently not supported by libiconv - $this->_codepage = ""; - break; - - } + $this->_codepage = PHPExcel_Shared_CodePage::NumberToName($codepage); } /** @@ -1633,7 +1610,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 0; size: 2; 0x087D = repeated header // offset: 2; size: 2 - + // offset: 4; size: 8; not used // offset: 12; size: 2; record version @@ -1645,19 +1622,19 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 18; size: 2; number of extension properties that follow $cexts = $this->_GetInt2d($recordData, 18); - + // start reading the actual extension data $offset = 20; while ($offset < $length) { // extension type $extType = $this->_GetInt2d($recordData, $offset); - + // extension length $cb = $this->_GetInt2d($recordData, $offset + 2); - + // extension data $extData = substr($recordData, $offset + 4, $cb); - + switch ($extType) { case 4: // fill start color $xclfType = $this->_GetInt2d($extData, 0); // color type @@ -1793,7 +1770,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } - + /** * Read STYLE record */ @@ -1881,7 +1858,6 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $rec_offset = $this->_GetInt4d($recordData, 0); // offset: 4; size: 1; sheet state - $rec_typeFlag = ord($recordData{4}); switch (ord($recordData{4})) { case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; case 0x01: $sheetState = PHPExcel_Worksheet::SHEETSTATE_HIDDEN; break; @@ -1890,7 +1866,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } // offset: 5; size: 1; sheet type - $rec_visibilityFlag = ord($recordData{5}); + $sheetType = ord($recordData{5}); // offset: 6; size: var; sheet name if ($this->_version == self::XLS_BIFF8) { @@ -1900,10 +1876,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $string = $this->_readByteStringShort(substr($recordData, 6)); $rec_name = $string['value']; } + $this->_sheets[] = array( 'name' => $rec_name, 'offset' => $rec_offset, 'sheetState' => $sheetState, + 'sheetType' => $sheetType, ); } @@ -1954,13 +1932,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $this->_externalBooks[] = array( 'type' => 'internal', ); - } elseif (substr($recordData, 0, 4) == pack('VCC', 0x0001, 0x01, 0x3A)) { + } elseif (substr($recordData, 0, 4) == pack('vCC', 0x0001, 0x01, 0x3A)) { // add-in function // offset: 0; size: 2; 0x0001 $this->_externalBooks[] = array( 'type' => 'addInFunction', ); - } elseif (substr($recordData, 0, 2) == pack('V', 0x0000)) { + } elseif (substr($recordData, 0, 2) == pack('v', 0x0000)) { // DDE links, OLE links // offset: 0; size: 2; 0x0000 // offset: 2; size: var; encoded source document name @@ -1970,6 +1948,40 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * Read EXTERNNAME record. + */ + private function _readExternName() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // external sheet references provided for named cells + if ($this->_version == self::XLS_BIFF8) { + // offset: 0; size: 2; options + $options = $this->_GetInt2d($recordData, 0); + + // offset: 2; size: 2; + + // offset: 4; size: 2; not used + + // offset: 6; size: var + $nameString = $this->_readUnicodeStringShort(substr($recordData, 6)); + + // offset: var; size: var; formula data + $offset = 6 + $nameString['size']; + $formula = $this->_getFormulaFromStructure(substr($recordData, $offset)); + + $this->_externalNames[] = array( + 'name' => $nameString['value'], + 'formula' => $formula, + ); + } + } + /** * Read EXTERNSHEET record */ @@ -2035,6 +2047,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // note: there can also be additional data, this is not included in $flen $flen = $this->_GetInt2d($recordData, 4); + // offset: 8; size: 2; 0=Global name, otherwise index to sheet (1-based) + $scope = $this->_GetInt2d($recordData, 8); + // offset: 14; size: var; Name (Unicode string without length field) $string = $this->_readUnicodeString(substr($recordData, 14), $nlen); @@ -2052,6 +2067,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader 'isBuiltInName' => $isBuiltInName, 'name' => $string['value'], 'formula' => $formula, + 'scope' => $scope, ); } } @@ -2851,13 +2867,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $rknum = $this->_GetInt4d($recordData, 6); $numValue = $this->_GetIEEE754($rknum); - // add style information + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + // add style information + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); } } @@ -2896,17 +2913,17 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell if (($fmtRuns = $this->_sst[$index]['fmtRuns']) && !$this->_readDataOnly) { // then we should treat as rich text - $richText = new PHPExcel_RichText($this->_phpSheet->getCell($columnString . ($row + 1))); + $richText = new PHPExcel_RichText(); $charPos = 0; for ($i = 0; $i <= count($this->_sst[$index]['fmtRuns']); ++$i) { if (isset($fmtRuns[$i])) { - $text = mb_substr($this->_sst[$index]['value'], $charPos, $fmtRuns[$i]['charPos'] - $charPos, 'UTF-8'); + $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, $fmtRuns[$i]['charPos'] - $charPos); $charPos = $fmtRuns[$i]['charPos']; } else { - $text = mb_substr($this->_sst[$index]['value'], $charPos, mb_strlen($this->_sst[$index]['value']), 'UTF-8'); + $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, PHPExcel_Shared_String::CountCharacters($this->_sst[$index]['value'])); } - if (mb_strlen($text) > 0) { + if (PHPExcel_Shared_String::CountCharacters($text) > 0) { if ($i == 0) { // first text run, no style $richText->createText($text); } else { @@ -2924,13 +2941,16 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } } + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($richText, PHPExcel_Cell_DataType::TYPE_STRING); } else { - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $this->_sst[$index]['value'], PHPExcel_Cell_DataType::TYPE_STRING); + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($this->_sst[$index]['value'], PHPExcel_Cell_DataType::TYPE_STRING); } - // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + // add style information + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -2975,13 +2995,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: var; size: 4; RK value $numValue = $this->_GetIEEE754($this->_GetInt4d($recordData, $offset + 2)); + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); if (!$this->_readDataOnly) { // add style - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell value - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); } $offset += 6; @@ -3018,13 +3039,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $numValue = $this->_extractNumber(substr($recordData, 6, 8)); - // add cell style + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell value - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); } } @@ -3051,33 +3073,35 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $column = $this->_GetInt2d($recordData, 2); $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + // offset: 20: size: variable; formula structure + $formulaStructure = substr($recordData, 20); + + // offset: 14: size: 2; option flags, recalculate always, recalculate on open etc. + $options = $this->_GetInt2d($recordData, 14); + + // bit: 0; mask: 0x0001; 1 = recalculate always + // bit: 1; mask: 0x0002; 1 = calculate on open + // bit: 2; mask: 0x0008; 1 = part of a shared formula + $isPartOfSharedFormula = (bool) (0x0008 & $options); + + // WARNING: + // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true + // the formula data may be ordinary formula data, therefore we need to check + // explicitly for the tExp token (0x01) + $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; + + if ($isPartOfSharedFormula) { + // part of shared formula which means there will be a formula with a tExp token and nothing else + // get the base cell, grab tExp token + $baseRow = $this->_GetInt2d($formulaStructure, 3); + $baseCol = $this->_GetInt2d($formulaStructure, 5); + $this->_baseCell = PHPExcel_Cell::stringFromColumnIndex($baseCol). ($baseRow + 1); + } + // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - // offset: 20: size: variable; formula structure - $formulaStructure = substr($recordData, 20); - - // offset: 14: size: 2; option flags, recalculate always, recalculate on open etc. - $options = $this->_GetInt2d($recordData, 14); - - // bit: 0; mask: 0x0001; 1 = recalculate always - // bit: 1; mask: 0x0002; 1 = calculate on open - // bit: 2; mask: 0x0008; 1 = part of a shared formula - $isPartOfSharedFormula = (bool) (0x0008 & $options); - - // WARNING: - // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true - // the formula data may be ordinary formula data, therefore we need to check - // explicitly for the tExp token (0x01) - $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; - if ($isPartOfSharedFormula) { - // part of shared formula which means there will be a formula with a tExp token and nothing else - // get the base cell, grab tExp token - $baseRow = $this->_GetInt2d($formulaStructure, 3); - $baseCol = $this->_GetInt2d($formulaStructure, 5); - $this->_baseCell = PHPExcel_Cell::stringFromColumnIndex($baseCol). ($baseRow + 1); - // formula is added to this cell after the sheet has been read $this->_sharedFormulaParts[$columnString . ($row + 1)] = $this->_baseCell; } @@ -3136,9 +3160,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } - // add cell style + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // store the formula @@ -3150,21 +3175,21 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader throw new Exception('Not BIFF8. Can only read BIFF8 formulas'); } $formula = $this->_getFormulaFromStructure($formulaStructure); // get formula in human language - $this->_phpSheet->getCell($columnString . ($row + 1))->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + $cell->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); } catch (Exception $e) { - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $value, $dataType); + $cell->setValueExplicit($value, $dataType); } } else { if ($this->_version == self::XLS_BIFF8) { // do nothing at this point, formula id added later in the code } else { - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $value, $dataType); + $cell->setValueExplicit($value, $dataType); } } // store the cached calculated value - $this->_phpSheet->getCell($columnString . ($row + 1))->setCalculatedValue($value); + $cell->setCalculatedValue($value); } } @@ -3258,25 +3283,26 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 7; size: 1; 0=boolean; 1=error $isError = ord($recordData{7}); + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); switch ($isError) { - case 0: // boolean - $value = (bool) $boolErr; + case 0: // boolean + $value = (bool) $boolErr; - // add cell value - $this->_phpSheet->getCell($columnString . ($row + 1))->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_BOOL); - break; + // add cell value + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_BOOL); + break; - case 1: // error type - $value = $this->_mapErrorCode($boolErr); + case 1: // error type + $value = $this->_mapErrorCode($boolErr); - // add cell value - $this->_phpSheet->getCell($columnString . ($row + 1))->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_ERROR); - break; + // add cell value + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_ERROR); + break; } - // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3359,11 +3385,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $string = $this->_readByteStringLong(substr($recordData, 6)); $value = $string['value']; } - $this->_phpSheet->setCellValueExplicit($columnString . ($row + 1), $value, PHPExcel_Cell_DataType::TYPE_STRING); + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); - // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3405,10 +3432,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readMsoDrawing() { $length = $this->_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; $this->_drawingData .= $recordData; } @@ -3459,6 +3486,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $showGridlines = (bool) ((0x0002 & $options) >> 1); $this->_phpSheet->setShowGridlines($showGridlines); + // bit: 2; mask: 0x0004; 0 = do not show headers, 1 = show headers + $showRowColHeaders = (bool) ((0x0004 & $options) >> 2); + $this->_phpSheet->setShowRowColHeaders($showRowColHeaders); + // bit: 3; mask: 0x0008; 0 = panes are not frozen, 1 = panes are frozen $this->_frozen = (bool) ((0x0008 & $options) >> 3); @@ -3550,7 +3581,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $cellRangeAddressList = $this->_readBIFF5CellRangeAddressList($data); // note: also BIFF8 uses BIFF5 syntax $selectedCells = $cellRangeAddressList['cellRangeAddresses'][0]; - + // first row '1' + last row '16384' indicates that full column is selected (apparently also in BIFF8!) if (preg_match('/^([A-Z]+1\:[A-Z]+)16384$/', $selectedCells)) { $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)16384$/', '${1}1048576', $selectedCells); @@ -3713,16 +3744,16 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: var; size: 4; size of the following file link field including string lenth mark $sz = $this->_GetInt4d($recordData, $offset); $offset += 4; - + // only present if $sz > 0 if ($sz > 0) { // offset: var; size: 4; size of the character array of the extended file path and name $xl = $this->_GetInt4d($recordData, $offset); $offset += 4; - + // offset: var; size 2; unknown $offset += 2; - + // offset: var; size $xl; character array of the extended file path and name. $extendedFilePath = substr($recordData, $offset, $xl); $extendedFilePath = $this->_encodeUTF16($extendedFilePath, false); @@ -3770,6 +3801,177 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * Read DATAVALIDATIONS record + */ + private function _readDataValidations() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + } + + /** + * Read DATAVALIDATION record + */ + private function _readDataValidation() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 4; Options + $options = $this->_GetInt4d($recordData, 0); + + // bit: 0-3; mask: 0x0000000F; type + $type = (0x0000000F & $options) >> 0; + switch ($type) { + case 0x00: $type = PHPExcel_Cell_DataValidation::TYPE_NONE; break; + case 0x01: $type = PHPExcel_Cell_DataValidation::TYPE_WHOLE; break; + case 0x02: $type = PHPExcel_Cell_DataValidation::TYPE_DECIMAL; break; + case 0x03: $type = PHPExcel_Cell_DataValidation::TYPE_LIST; break; + case 0x04: $type = PHPExcel_Cell_DataValidation::TYPE_DATE; break; + case 0x05: $type = PHPExcel_Cell_DataValidation::TYPE_TIME; break; + case 0x06: $type = PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH; break; + case 0x07: $type = PHPExcel_Cell_DataValidation::TYPE_CUSTOM; break; + } + + // bit: 4-6; mask: 0x00000070; error type + $errorStyle = (0x00000070 & $options) >> 4; + switch ($errorStyle) { + case 0x00: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; break; + case 0x01: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_WARNING; break; + case 0x02: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_INFORMATION; break; + } + + // bit: 7; mask: 0x00000080; 1= formula is explicit (only applies to list) + // I have only seen cases where this is 1 + $explicitFormula = (0x00000080 & $options) >> 7; + + // bit: 8; mask: 0x00000100; 1= empty cells allowed + $allowBlank = (0x00000100 & $options) >> 8; + + // bit: 9; mask: 0x00000200; 1= suppress drop down arrow in list type validity + $suppressDropDown = (0x00000200 & $options) >> 9; + + // bit: 18; mask: 0x00040000; 1= show prompt box if cell selected + $showInputMessage = (0x00040000 & $options) >> 18; + + // bit: 19; mask: 0x00080000; 1= show error box if invalid values entered + $showErrorMessage = (0x00080000 & $options) >> 19; + + // bit: 20-23; mask: 0x00F00000; condition operator + $operator = (0x00F00000 & $options) >> 20; + switch ($operator) { + case 0x00: $operator = PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN ; break; + case 0x01: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN ; break; + case 0x02: $operator = PHPExcel_Cell_DataValidation::OPERATOR_EQUAL ; break; + case 0x03: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL ; break; + case 0x04: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN ; break; + case 0x05: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN ; break; + case 0x06: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL; break; + case 0x07: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL ; break; + } + + // offset: 4; size: var; title of the prompt box + $offset = 4; + $string = $this->_readUnicodeStringLong(substr($recordData, $offset)); + $promptTitle = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; title of the error box + $string = $this->_readUnicodeStringLong(substr($recordData, $offset)); + $errorTitle = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; text of the prompt box + $string = $this->_readUnicodeStringLong(substr($recordData, $offset)); + $prompt = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; text of the error box + $string = $this->_readUnicodeStringLong(substr($recordData, $offset)); + $error = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: 2; size of the formula data for the first condition + $sz1 = $this->_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 2; not used + $offset += 2; + + // offset: var; size: $sz1; formula data for first condition (without size field) + $formula1 = substr($recordData, $offset, $sz1); + $formula1 = pack('v', $sz1) . $formula1; // prepend the length + try { + $formula1 = $this->_getFormulaFromStructure($formula1); + + // in list type validity, null characters are used as item separators + if ($type == PHPExcel_Cell_DataValidation::TYPE_LIST) { + $formula1 = str_replace(chr(0), ',', $formula1); + } + } catch (Exception $e) { + return; + } + $offset += $sz1; + + // offset: var; size: 2; size of the formula data for the first condition + $sz2 = $this->_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 2; not used + $offset += 2; + + // offset: var; size: $sz2; formula data for second condition (without size field) + $formula2 = substr($recordData, $offset, $sz2); + $formula2 = pack('v', $sz2) . $formula2; // prepend the length + try { + $formula2 = $this->_getFormulaFromStructure($formula2); + } catch (Exception $e) { + return; + } + $offset += $sz2; + + // offset: var; size: var; cell range address list with + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList(substr($recordData, $offset)); + $cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses']; + + foreach ($cellRangeAddresses as $cellRange) { + $stRange = $this->_phpSheet->shrinkRangeToFit($cellRange); + $stRange = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); + foreach ($stRange as $coordinate) { + $objValidation = $this->_phpSheet->getCell($coordinate)->getDataValidation(); + $objValidation->setType($type); + $objValidation->setErrorStyle($errorStyle); + $objValidation->setAllowBlank((bool)$allowBlank); + $objValidation->setShowInputMessage((bool)$showInputMessage); + $objValidation->setShowErrorMessage((bool)$showErrorMessage); + $objValidation->setShowDropDown(!$suppressDropDown); + $objValidation->setOperator($operator); + $objValidation->setErrorTitle($errorTitle); + $objValidation->setError($error); + $objValidation->setPromptTitle($promptTitle); + $objValidation->setPrompt($prompt); + $objValidation->setFormula1($formula1); + $objValidation->setFormula2($formula2); + } + } + + } + /** * Read SHEETLAYOUT record. Stores sheet tab color information. */ @@ -3810,7 +4012,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } /** - * Read SHEETPROTECTION record + * Read SHEETPROTECTION record (FEATHEADR) */ private function _readSheetProtection() { @@ -3826,10 +4028,21 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 0; size: 2; repeated record header - // offset: 2; size: 9; not used + // offset: 2; size: 2; FRT cell reference flag (=0 currently) - // offset: 11; size: 8; unknown data + // offset: 4; size: 8; Currently not used and set to 0 + // offset: 12; size: 2; Shared feature type index (2=Enhanced Protetion, 4=SmartTag) + $isf = $this->_GetInt2d($recordData, 12); + if ($isf != 2) { + return; + } + + // offset: 14; size: 1; =1 since this is a feat header + + // offset: 15; size: 4; size of rgbHdrSData + + // rgbHdrSData, assume "Enhanced Protection" // offset: 19; size: 2; option flags $options = $this->_GetInt2d($recordData, 19); @@ -3895,7 +4108,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 21; size: 2; not used } - + /** * Read RANGEPROTECTION record * Reading of this record is based on Microsoft Office Excel 97-2000 Binary File Format Specification, @@ -4048,17 +4261,20 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $length = $this->_GetInt2d($this->_data, $this->_pos + 2); $recordData = substr($this->_data, $this->_pos + 4, $length); - // move stream pointer to next record - $this->_pos += 4 + $length; - // check if we are reading drawing data // this is in case a free CONTINUE record occurs in other circumstances we are unaware of if ($this->_drawingData == '') { + // move stream pointer to next record + $this->_pos += 4 + $length; + return; } // check if record data is at least 4 bytes long, otherwise there is no chance this is MSODRAWING data - if (strlen($recordData) < 4) { + if ($length < 4) { + // move stream pointer to next record + $this->_pos += 4 + $length; + return; } @@ -4072,8 +4288,16 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $splitPoint = $this->_GetInt2d($recordData, 2); if (in_array($splitPoint, $validSplitPoints)) { - $this->_drawingData .= $recordData; + // get spliced record data (and move pointer to next record) + $splicedRecordData = $this->_getSplicedRecordData(); + $this->_drawingData .= $splicedRecordData['recordData']; + + return; } + + // move stream pointer to next record + $this->_pos += 4 + $length; + } @@ -4276,13 +4500,26 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader break; case 'tFunc': // function with fixed number of arguments case 'tFuncV': // function with variable number of arguments - $ops = array(); // array of operators - for ($i = 0; $i < $token['data']['args']; ++$i) { - $ops[] = array_pop($formulaStrings); + if ($token['data']['function'] != '') { + // normal function + $ops = array(); // array of operators + for ($i = 0; $i < $token['data']['args']; ++$i) { + $ops[] = array_pop($formulaStrings); + } + $ops = array_reverse($ops); + $formulaStrings[] = "$space1$space0{$token['data']['function']}(" . implode(',', $ops) . ")"; + unset($space0, $space1); + } else { + // add-in function + $ops = array(); // array of operators + for ($i = 0; $i < $token['data']['args'] - 1; ++$i) { + $ops[] = array_pop($formulaStrings); + } + $ops = array_reverse($ops); + $function = array_pop($formulaStrings); + $formulaStrings[] = "$space1$space0$function(" . implode(',', $ops) . ")"; + unset($space0, $space1); } - $ops = array_reverse($ops); - $formulaStrings[] = "$space1$space0{$token['data']['function']}(" . implode(',', $ops) . ")"; - unset($space0, $space1); break; case 'tParen': // parenthesis $expression = array_pop($formulaStrings); @@ -4310,6 +4547,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 'tMemFunc': case 'tMissArg': case 'tName': + case 'tNameX': case 'tNum': // number case 'tRef': // single cell reference case 'tRef3d': // 3d cell reference @@ -4661,7 +4899,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 1; size: 1; number of arguments $args = ord($formulaData[1]); // offset: 2: size: 2; index to built-in sheet function - switch ($this->_GetInt2d($formulaData, 2)) { + $index = $this->_GetInt2d($formulaData, 2); + switch ($index) { case 0: $function = 'COUNT'; break; case 1: $function = 'IF'; break; case 4: $function = 'SUM'; break; @@ -4723,6 +4962,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 227: $function = 'MEDIAN'; break; case 228: $function = 'SUMPRODUCT'; break; case 247: $function = 'DB'; break; + case 255: $function = ''; break; case 269: $function = 'AVEDEV'; break; case 270: $function = 'BETADIST'; break; case 272: $function = 'BETAINV'; break; @@ -4803,7 +5043,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $size = 3 + $subSize; $data = $this->_getFormulaFromData(substr($formulaData, 3, $subSize)); break; - + case 0x2C: // Relative reference, used in shared formulas and some other places case 0x4C: case 0x6C: @@ -4811,7 +5051,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $size = 5; $data = $this->_readBIFF8CellAddressB(substr($formulaData, 1, 4), $baseCell); break; - + case 0x2D: case 0x4D: case 0x6D: @@ -4820,28 +5060,56 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $data = $this->_readBIFF8CellRangeAddressB(substr($formulaData, 1, 8), $baseCell); break; + case 0x39: + case 0x59: + case 0x79: + $name = 'tNameX'; + $size = 7; + // offset: 1; size: 2; index to REF entry in EXTERNSHEET record + // offset: 3; size: 2; one-based index to DEFINEDNAME or EXTERNNAME record + $index = $this->_GetInt2d($formulaData, 3); + // assume index is to EXTERNNAME record + $data = $this->_externalNames[$index - 1]['name']; + // offset: 5; size: 2; not used + break; + case 0x3A: // 3d reference to cell case 0x5A: $name = 'tRef3d'; $size = 7; - // offset: 1; size: 2; index to REF entry - $sheetRange = $this->_readSheetRangeByRefIndex($this->_GetInt2d($formulaData, 1)); - // offset: 3; size: 4; cell address - $cellAddress = $this->_readBIFF8CellAddress(substr($formulaData, 3, 4)); - $data = "$sheetRange!$cellAddress"; + try { + // offset: 1; size: 2; index to REF entry + $sheetRange = $this->_readSheetRangeByRefIndex($this->_GetInt2d($formulaData, 1)); + // offset: 3; size: 4; cell address + $cellAddress = $this->_readBIFF8CellAddress(substr($formulaData, 3, 4)); + + $data = "$sheetRange!$cellAddress"; + + } catch (Exception $e) { + // deleted sheet reference + $data = '#REF!'; + } break; case 0x3B: // 3d reference to cell range case 0x5B: $name = 'tArea3d'; $size = 11; - // offset: 1; size: 2; index to REF entry - $sheetRange = $this->_readSheetRangeByRefIndex($this->_GetInt2d($formulaData, 1)); - // offset: 3; size: 8; cell address - $cellRangeAddress = $this->_readBIFF8CellRangeAddress(substr($formulaData, 3, 8)); - $data = "$sheetRange!$cellRangeAddress"; + try { + // offset: 1; size: 2; index to REF entry + $sheetRange = $this->_readSheetRangeByRefIndex($this->_GetInt2d($formulaData, 1)); + // offset: 3; size: 8; cell address + $cellRangeAddress = $this->_readBIFF8CellRangeAddress(substr($formulaData, 3, 8)); + + $data = "$sheetRange!$cellRangeAddress"; + + } catch (Exception $e) { + // deleted sheet reference + $data = '#REF!'; + + } break; // case 0x39: // don't know how to deal with @@ -4900,7 +5168,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader { list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; - + // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) $rowIndex = $this->_GetInt2d($cellAddressStructure, 0); $row = $this->_GetInt2d($cellAddressStructure, 0) + 1; @@ -5209,7 +5477,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader if (isset($this->_ref[$index])) { $type = $this->_externalBooks[$this->_ref[$index]['externalBookIndex']]['type']; - + switch ($type) { case 'internal': // check if we have a deleted 3d reference diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php b/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php index fd9f138ed..e0a975e22 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php @@ -22,41 +22,9 @@ * @package PHPExcel_Reader_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Shared_Escher_DggContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php'; - -/** PHPExcel_Shared_Escher_DgContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer.php'; - -/** PHPExcel_Shared_Escher_DgContainer_SpgrContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php'; - -/** PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php'; - /** * PHPExcel_Reader_Excel5_Escher * @@ -122,7 +90,7 @@ class PHPExcel_Reader_Excel5_Escher { $this->_object = $object; } - + /** * Load Escher stream data. May be a partial Escher stream. * @@ -136,14 +104,14 @@ class PHPExcel_Reader_Excel5_Escher $this->_dataSize = strlen($this->_data); $this->_pos = 0; - + // Parse Escher stream while ($this->_pos < $this->_dataSize) { - - + + // offset: 2; size: 2: Record Type $fbt = $this->_GetInt2d($this->_data, $this->_pos + 2); - + switch ($fbt) { case self::DGGCONTAINER: $this->_readDggContainer(); break; case self::DGG: $this->_readDgg(); break; @@ -166,7 +134,7 @@ class PHPExcel_Reader_Excel5_Escher default: $this->_readDefault(); break; } } - + return $this->_object; } @@ -177,16 +145,16 @@ class PHPExcel_Reader_Excel5_Escher { // offset 0; size: 2; recVer and recInstance $verInstance = $this->_GetInt2d($this->_data, $this->_pos); - + // offset: 2; size: 2: Record Type $fbt = $this->_GetInt2d($this->_data, $this->_pos + 2); // bit: 0-3; mask: 0x000F; recVer $recVer = (0x000F & $verInstance) >> 0; - + $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; } @@ -216,7 +184,7 @@ class PHPExcel_Reader_Excel5_Escher { $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; } @@ -245,22 +213,22 @@ class PHPExcel_Reader_Excel5_Escher private function _readBSE() { // offset: 0; size: 2; recVer and recInstance - + // bit: 4-15; mask: 0xFFF0; recInstance $recInstance = (0xFFF0 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4; $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; - + // add BSE to BstoreContainer $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); $this->_object->addBSE($BSE); $BSE->setBLIPType($recInstance); - + // offset: 0; size: 1; btWin32 (MSOBLIPTYPE) $btWin32 = ord($recordData[0]); @@ -311,38 +279,38 @@ class PHPExcel_Reader_Excel5_Escher private function _readBlipJPEG() { // offset: 0; size: 2; recVer and recInstance - + // bit: 4-15; mask: 0xFFF0; recInstance $recInstance = (0xFFF0 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4; $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; - + $pos = 0; - + // offset: 0; size: 16; rgbUid1 (MD4 digest of) $rgbUid1 = substr($recordData, 0, 16); $pos += 16; - + // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 if (in_array($recInstance, array(0x046B, 0x06E3))) { $rgbUid2 = substr($recordData, 16, 16); $pos += 16; } - + // offset: var; size: 1; tag $tag = ord($recordData{$pos}); $pos += 1; - + // offset: var; size: var; the raw image data $data = substr($recordData, $pos); - + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); $blip->setData($data); - + $this->_object->setBlip($blip); } @@ -352,38 +320,38 @@ class PHPExcel_Reader_Excel5_Escher private function _readBlipPNG() { // offset: 0; size: 2; recVer and recInstance - + // bit: 4-15; mask: 0xFFF0; recInstance $recInstance = (0xFFF0 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4; $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; - + $pos = 0; - + // offset: 0; size: 16; rgbUid1 (MD4 digest of) $rgbUid1 = substr($recordData, 0, 16); $pos += 16; - + // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 if ($recInstance == 0x06E1) { $rgbUid2 = substr($recordData, 16, 16); $pos += 16; } - + // offset: var; size: 1; tag $tag = ord($recordData{$pos}); $pos += 1; - + // offset: var; size: var; the raw image data $data = substr($recordData, $pos); - + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); $blip->setData($data); - + $this->_object->setBlip($blip); } @@ -393,13 +361,13 @@ class PHPExcel_Reader_Excel5_Escher private function _readOPT() { // offset: 0; size: 2; recVer and recInstance - + // bit: 4-15; mask: 0xFFF0; recInstance $recInstance = (0xFFF0 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4; $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; @@ -412,7 +380,7 @@ class PHPExcel_Reader_Excel5_Escher private function _readTertiaryOPT() { // offset: 0; size: 2; recVer and recInstance - + // bit: 4-15; mask: 0xFFF0; recInstance $recInstance = (0xFFF0 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4; @@ -566,10 +534,10 @@ class PHPExcel_Reader_Excel5_Escher { $length = $this->_GetInt4d($this->_data, $this->_pos + 4); $recordData = substr($this->_data, $this->_pos + 8, $length); - + // move stream pointer to next record $this->_pos += 8 + $length; - + // offset: 2; size: 2; upper-left corner column index (0-based) $c1 = $this->_GetInt2d($recordData, 2); diff --git a/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php b/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php index c81297176..6d8ee6d92 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php +++ b/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Reader/IReader.php b/libraries/PHPExcel/PHPExcel/Reader/IReader.php index 52e0c2e89..e1a5b9865 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/IReader.php +++ b/libraries/PHPExcel/PHPExcel/Reader/IReader.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php b/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php index 618a1f2d4..38f9eaea1 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php +++ b/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,27 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Calculation */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; - - /** PHPExcel_Reader_DefaultReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; - - /** * PHPExcel_Reader_OOCalc * @@ -211,6 +199,7 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader * Loads PHPExcel from file * * @param string $pFilename + * @return PHPExcel * @throws Exception */ public function load($pFilename) @@ -238,6 +227,7 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader * * @param string $pFilename * @param PHPExcel $objPHPExcel + * @return PHPExcel * @throws Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) @@ -335,7 +325,7 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader $objPHPExcel->createSheet(); $objPHPExcel->setActiveSheetIndex($worksheetID); if (isset($worksheetDataAttributes['name'])) { - $worksheetName = $worksheetDataAttributes['name']; + $worksheetName = (string) $worksheetDataAttributes['name']; $objPHPExcel->getActiveSheet()->setTitle($worksheetName); } @@ -392,7 +382,9 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader break; case 'date' : $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellDataOfficeAttributes['date-value'])); + $dateObj = date_create($cellDataOfficeAttributes['date-value']); + list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s')); + $dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second); if ($dataValue != floor($dataValue)) { $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; } else { @@ -421,6 +413,7 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader if (($key % 2) == 0) { $value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value); $value = preg_replace('/\[\.(.*)\]/Ui','$1',$value); + $value = PHPExcel_Calculation::_translateSeparator(';',',',$value); } } unset($value); diff --git a/libraries/PHPExcel/PHPExcel/Reader/SYLK.php b/libraries/PHPExcel/PHPExcel/Reader/SYLK.php index a9bd64717..d93cb379c 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/SYLK.php +++ b/libraries/PHPExcel/PHPExcel/Reader/SYLK.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,27 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Calculation */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; - - /** PHPExcel_Reader_DefaultReadFilter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; - - /** * PHPExcel_Reader_SYLK * @@ -167,6 +155,7 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader * Loads PHPExcel from file * * @param string $pFilename + * @return PHPExcel * @throws Exception */ public function load($pFilename) @@ -194,6 +183,7 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader */ public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { $this->_readFilter = $pValue; + return $this; } /** @@ -204,6 +194,7 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader public function setInputEncoding($pValue = 'ANSI') { $this->_inputEncoding = $pValue; + return $this; } /** @@ -221,6 +212,7 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader * * @param string $pFilename * @param PHPExcel $objPHPExcel + * @return PHPExcel * @throws Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) @@ -248,8 +240,17 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader // Loop through file $rowData = array(); $column = $row = ''; + + // loop through one row (line) at a time in the file while (($rowData = fgets($fileHandle)) !== FALSE) { - $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + + // convert SYLK encoded $rowData to UTF-8 + $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); + + // explode each row at semicolons while taking into account that literal semicolon (;) + // is escaped like this (;;) + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + $dataType = array_shift($rowData); // Read shared styles if ($dataType == 'P') { @@ -337,8 +338,9 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader } $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + // Set cell value - $objPHPExcel->getActiveSheet()->setCellValue($columnLetter.$row, (($hasCalculatedValue) ? $cellDataFormula : $cellData)); + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData); if ($hasCalculatedValue) { $cellData = PHPExcel_Calculation::_unwrapResult($cellData); $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData); @@ -503,4 +505,5 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader $this->_sheetIndex = $pValue; return $this; } + } diff --git a/libraries/PHPExcel/PHPExcel/Reader/Serialized.php b/libraries/PHPExcel/PHPExcel/Reader/Serialized.php index 120a6781c..fd4df9f64 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Serialized.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Serialized.php @@ -22,7 +22,7 @@ * @package PHPExcel_Reader * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -32,18 +32,15 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Reader_IReader */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; - -/** PHPExcel_Shared_File */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; - - /** * PHPExcel_Reader_Serialized * @@ -58,17 +55,17 @@ class PHPExcel_Reader_Serialized implements PHPExcel_Reader_IReader * * @param string $pFileName * @return boolean - */ - public function canRead($pFilename) + */ + public function canRead($pFilename) { // Check if file exists if (!file_exists($pFilename)) { throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); } - + return $this->fileSupportsUnserializePHPExcel($pFilename); } - + /** * Loads PHPExcel Serialized file * diff --git a/libraries/PHPExcel/PHPExcel/ReferenceHelper.php b/libraries/PHPExcel/PHPExcel/ReferenceHelper.php index 175bba122..da288c5d0 100644 --- a/libraries/PHPExcel/PHPExcel/ReferenceHelper.php +++ b/libraries/PHPExcel/PHPExcel/ReferenceHelper.php @@ -22,40 +22,10 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Style */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; - -/** PHPExcel_Worksheet_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; - -/** PHPExcel_Calculation_FormulaParser */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaParser.php'; - -/** PHPExcel_Calculation_FormulaToken */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaToken.php'; - - /** * PHPExcel_ReferenceHelper (Singleton) * @@ -100,12 +70,6 @@ class PHPExcel_ReferenceHelper * @throws Exception */ public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { - // Get a copy of the cell collection - /*$aTemp = $pSheet->getCellCollection(); - $aCellCollection = array(); - foreach ($aTemp as $key => $value) { - $aCellCollection[$key] = clone $value; - }*/ $aCellCollection = $pSheet->getCellCollection(); // Get coordinates of $pBefore @@ -148,7 +112,9 @@ class PHPExcel_ReferenceHelper // Loop through cells, bottom-up, and change cell coordinates - while ( ($cell = ($pNumCols < 0 || $pNumRows < 0) ? array_shift($aCellCollection) : array_pop($aCellCollection)) ) { + while (($cellID = ($pNumCols < 0 || $pNumRows < 0) ? array_shift($aCellCollection) : array_pop($aCellCollection))) { + $cell = $pSheet->getCell($cellID); + // New coordinates $newCoordinates = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1 + $pNumCols ) . ($cell->getRow() + $pNumRows); @@ -165,17 +131,15 @@ class PHPExcel_ReferenceHelper // Insert this cell at its new location if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { // Formula should be adjusted - $pSheet->setCellValue( - $newCoordinates - , $this->updateFormulaReferences($cell->getValue(), $pBefore, $pNumCols, $pNumRows) - ); + $pSheet->getCell($newCoordinates) + ->setValue($this->updateFormulaReferences($cell->getValue(), $pBefore, $pNumCols, $pNumRows)); } else { // Formula should not be adjusted - $pSheet->setCellValue($newCoordinates, $cell->getValue()); + $pSheet->getCell($newCoordinates)->setValue($cell->getValue()); } // Clear the original cell - $pSheet->setCellValue($cell->getCoordinate(), ''); + $pSheet->getCell($cell->getCoordinate())->setValue(''); } } @@ -459,9 +423,10 @@ class PHPExcel_ReferenceHelper if ($oldName == '') { return; } - + foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { - foreach ($sheet->getCellCollection(false) as $cell) { + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); if (!is_null($cell) && $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { $formula = $cell->getValue(); if (strpos($formula, $oldName) !== false) { diff --git a/libraries/PHPExcel/PHPExcel/RichText.php b/libraries/PHPExcel/PHPExcel/RichText.php index aca7796ea..cd43573f8 100644 --- a/libraries/PHPExcel/PHPExcel/RichText.php +++ b/libraries/PHPExcel/PHPExcel/RichText.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,39 +22,10 @@ * @package PHPExcel_RichText * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_RichText_ITextElement */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText/ITextElement.php'; - -/** PHPExcel_RichText_TextElement */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText/TextElement.php'; - -/** PHPExcel_RichText_Run */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText/Run.php'; - -/** PHPExcel_Style_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; - /** * PHPExcel_RichText * @@ -70,14 +41,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable * @var PHPExcel_RichText_ITextElement[] */ private $_richTextElements; - - /** - * Parent cell - * - * @var PHPExcel_Cell - */ - private $_parent; - + /** * Create a new PHPExcel_RichText instance * @@ -88,24 +52,21 @@ class PHPExcel_RichText implements PHPExcel_IComparable { // Initialise variables $this->_richTextElements = array(); - - // Set parent? + + // Rich-Text string attached to cell? if (!is_null($pCell)) { - // Set parent cell - $this->_parent = $pCell; - // Add cell text and style - if ($this->_parent->getValue() != "") { - $objRun = new PHPExcel_RichText_Run($this->_parent->getValue()); - $objRun->setFont(clone $this->_parent->getParent()->getStyle($this->_parent->getCoordinate())->getFont()); + if ($pCell->getValue() != "") { + $objRun = new PHPExcel_RichText_Run($pCell->getValue()); + $objRun->setFont(clone $pCell->getParent()->getStyle($pCell->getCoordinate())->getFont()); $this->addText($objRun); } - + // Set parent value - $this->_parent->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING); + $pCell->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING); } } - + /** * Add text * @@ -118,7 +79,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable $this->_richTextElements[] = $pText; return $this; } - + /** * Create text * @@ -132,7 +93,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable $this->addText($objText); return $objText; } - + /** * Create text run * @@ -146,7 +107,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable $this->addText($objText); return $objText; } - + /** * Get plain text * @@ -156,16 +117,16 @@ class PHPExcel_RichText implements PHPExcel_IComparable { // Return value $returnValue = ''; - + // Loop through all PHPExcel_RichText_ITextElement foreach ($this->_richTextElements as $text) { $returnValue .= $text->getText(); } - + // Return return $returnValue; } - + /** * Convert to string * @@ -174,7 +135,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable public function __toString() { return $this->getPlainText(); } - + /** * Get Rich Text elements * @@ -184,7 +145,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable { return $this->_richTextElements; } - + /** * Set Rich Text elements * @@ -201,70 +162,30 @@ class PHPExcel_RichText implements PHPExcel_IComparable } return $this; } - - /** - * Get parent - * - * @return PHPExcel_Cell - */ - public function getParent() { - return $this->_parent; - } - - /** - * Set parent - * - * @param PHPExcel_Cell $value - * @return PHPExcel_RichText - */ - public function setParent(PHPExcel_Cell $value) { - // Set parent - $this->_parent = $value; - - // Set parent value - $this->_parent->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING); - - // Verify style information - $sheet = $this->_parent->getParent(); - $cellFont = $sheet->getStyle($this->_parent->getCoordinate())->getFont()->getSharedComponent(); - foreach ($this->getRichTextElements() as $element) { - if (!($element instanceof PHPExcel_RichText_Run)) continue; - - if ($element->getFont()->getHashCode() == $sheet->getDefaultStyle()->getFont()->getHashCode()) { - if ($element->getFont()->getHashCode() != $cellFont->getHashCode()) { - $element->setFont(clone $cellFont); - } - } - } - return $this; - } - /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { $hashElements = ''; foreach ($this->_richTextElements as $element) { $hashElements .= $element->getHashCode(); } - + return md5( $hashElements . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ public function __clone() { $vars = get_object_vars($this); foreach ($vars as $key => $value) { - if ($key == '_parent') continue; - if (is_object($value)) { $this->$key = clone $value; } else { diff --git a/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php b/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php index 713a522c0..001361edd 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php +++ b/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php @@ -6,12 +6,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -20,22 +20,10 @@ * @package PHPExcel_RichText * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Style_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; - - /** * PHPExcel_RichText_ITextElement * @@ -49,28 +37,28 @@ interface PHPExcel_RichText_ITextElement * Get text * * @return string Text - */ + */ public function getText(); - + /** * Set text * * @param $pText string Text * @return PHPExcel_RichText_ITextElement - */ + */ public function setText($pText = ''); - + /** * Get font * * @return PHPExcel_Style_Font - */ + */ public function getFont(); - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode(); } diff --git a/libraries/PHPExcel/PHPExcel/RichText/Run.php b/libraries/PHPExcel/PHPExcel/RichText/Run.php index 82aff89c8..29a291b73 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/Run.php +++ b/libraries/PHPExcel/PHPExcel/RichText/Run.php @@ -6,12 +6,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -20,28 +20,10 @@ * @package PHPExcel_RichText * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_RichText_ITextElement */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText/ITextElement.php'; - -/** PHPExcel_RichText_TextElement */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText/TextElement.php'; - -/** PHPExcel_Style_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; - - /** * PHPExcel_RichText_Run * @@ -50,14 +32,14 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement -{ +{ /** * Font * * @var PHPExcel_Style_Font */ private $_font; - + /** * Create a new PHPExcel_RichText_Run instance * @@ -69,33 +51,33 @@ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHP $this->setText($pText); $this->_font = new PHPExcel_Style_Font(); } - + /** * Get font * * @return PHPExcel_Style_Font - */ + */ public function getFont() { return $this->_font; } - + /** * Set font * * @param PHPExcel_Style_Font $pFont Font * @throws Exception * @return PHPExcel_RichText_ITextElement - */ + */ public function setFont(PHPExcel_Style_Font $pFont = null) { $this->_font = $pFont; return $this; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->getText() @@ -103,7 +85,7 @@ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHP . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/RichText/TextElement.php b/libraries/PHPExcel/PHPExcel/RichText/TextElement.php index d16a92995..5598d4feb 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/TextElement.php +++ b/libraries/PHPExcel/PHPExcel/RichText/TextElement.php @@ -6,12 +6,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -20,25 +20,10 @@ * @package PHPExcel_RichText * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_RichText_ITextElement */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText/ITextElement.php'; - -/** PHPExcel_Style_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; - - /** * PHPExcel_RichText_TextElement * @@ -54,7 +39,7 @@ class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement * @var string */ private $_text; - + /** * Create a new PHPExcel_RichText_TextElement instance * @@ -65,48 +50,48 @@ class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement // Initialise variables $this->_text = $pText; } - + /** * Get text * * @return string Text - */ + */ public function getText() { return $this->_text; } - + /** * Set text * * @param $pText string Text * @return PHPExcel_RichText_ITextElement - */ + */ public function setText($pText = '') { $this->_text = $pText; return $this; } - + /** * Get font * * @return PHPExcel_Style_Font - */ + */ public function getFont() { return null; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_text . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Settings.php b/libraries/PHPExcel/PHPExcel/Settings.php new file mode 100644 index 000000000..27e39f953 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Settings.php @@ -0,0 +1,65 @@ +setLocale($locale); + } // function setLocale() + +} \ No newline at end of file diff --git a/libraries/PHPExcel/PHPExcel/Shared/CodePage.php b/libraries/PHPExcel/PHPExcel/Shared/CodePage.php new file mode 100644 index 000000000..23f28d003 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Shared/CodePage.php @@ -0,0 +1,94 @@ +"")) + $read .= fread($file,1024); + + $temp = unpack("H*",$read); + $hex = $temp[1]; + $header = substr($hex,0,108); + + // Process the header + // Structure: http://www.fastgraph.com/help/bmp_header_format.html + if (substr($header,0,4)=="424d") + { + // Cut it in parts of 2 bytes + $header_parts = str_split($header,2); + + // Get the width 4 bytes + $width = hexdec($header_parts[19].$header_parts[18]); + + // Get the height 4 bytes + $height = hexdec($header_parts[23].$header_parts[22]); + + // Unset the header params + unset($header_parts); + } + + // Define starting X and Y + $x = 0; + $y = 1; + + // Create newimage + $image = imagecreatetruecolor($width,$height); + + // Grab the body from the image + $body = substr($hex,108); + + // Calculate if padding at the end-line is needed + // Divided by two to keep overview. + // 1 byte = 2 HEX-chars + $body_size = (strlen($body)/2); + $header_size = ($width*$height); + + // Use end-line padding? Only when needed + $usePadding = ($body_size>($header_size*3)+4); + + // Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption + // Calculate the next DWORD-position in the body + for ($i=0;$i<$body_size;$i+=3) + { + // Calculate line-ending and padding + if ($x>=$width) + { + // If padding needed, ignore image-padding + // Shift i to the ending of the current 32-bit-block + if ($usePadding) + $i += $width%4; + + // Reset horizontal position + $x = 0; + + // Raise the height-position (bottom-up) + $y++; + + // Reached the image-height? Break the for-loop + if ($y>$height) + break; + } + + // Calculation of the RGB-pixel (defined as BGR in image-data) + // Define $i_pos as absolute position in the body + $i_pos = $i*2; + $r = hexdec($body[$i_pos+4].$body[$i_pos+5]); + $g = hexdec($body[$i_pos+2].$body[$i_pos+3]); + $b = hexdec($body[$i_pos].$body[$i_pos+1]); + + // Calculate and draw the pixel + $color = imagecolorallocate($image,$r,$g,$b); + imagesetpixel($image,$x,$height-$y,$color); + + // Raise the horizontal position + $x++; + } + + // Unset the body / free the memory + unset($body); + + // Return image-object + return $image; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher.php b/libraries/PHPExcel/PHPExcel/Shared/Escher.php index 4ed04b384..7c4edcdd4 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php index 243dab350..55df1acfd 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php index 8f07e52ae..f0c6933e8 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php index 952685307..914235f53 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php index 5883ae26b..e7b4d46bd 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php index c15995a63..070fdb8be 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php index 0ae494851..b753d45fb 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php index 87609cca7..47fcb75e6 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Escher * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ /** diff --git a/libraries/PHPExcel/PHPExcel/Shared/Excel5.php b/libraries/PHPExcel/PHPExcel/Shared/Excel5.php index f9b3f818a..8d3fb3601 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Excel5.php @@ -22,26 +22,9 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Shared_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; - -/** PHPExcel_Shared_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; - /** * PHPExcel_Shared_Excel5 * @@ -264,7 +247,7 @@ class PHPExcel_Shared_Excel5 list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinates); $col_start = PHPExcel_Cell::columnIndexFromString($column) - 1; $row_start = $row - 1; - + $x1 = $offsetX; $y1 = $offsetY; diff --git a/libraries/PHPExcel/PHPExcel/Shared/File.php b/libraries/PHPExcel/PHPExcel/Shared/File.php index a742d152f..94445052f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/File.php +++ b/libraries/PHPExcel/PHPExcel/Shared/File.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/Font.php b/libraries/PHPExcel/PHPExcel/Shared/Font.php index 8bf67d5b3..5ca6501b2 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Font.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Font.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - - /** * PHPExcel_Shared_Font * @@ -71,7 +59,7 @@ class PHPExcel_Shared_Font const CHARSET_ANSI_THAI = 0xDE; const CHARSET_ANSI_LATIN_II = 0xEE; const CHARSET_OEM_LATIN_I = 0xFF; - + // XXX: Constants created! /** Font filenames */ const ARIAL = 'arial.ttf'; @@ -230,7 +218,7 @@ class PHPExcel_Shared_Font { self::$trueTypeFontPath = $pValue; } - + /** * Get the path to the folder containing .ttf files. * @@ -240,26 +228,31 @@ class PHPExcel_Shared_Font { return self::$trueTypeFontPath; } - + /** * Calculate an (approximate) OpenXML column width, based on font size and text contained * * @param int $fontSize Font size (in pixels or points) * @param bool $fontSizeInPixels Is the font size specified in pixels (true) or in points (false) ? - * @param string $columnText Text to calculate width + * @param string $cellText Text to calculate width * @param int $rotation Rotation angle * @return int Column width */ - public static function calculateColumnWidth(PHPExcel_Style_Font $font, $columnText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { + public static function calculateColumnWidth(PHPExcel_Style_Font $font, $cellText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { // If it is rich text, use plain text - if ($columnText instanceof PHPExcel_RichText) { - $columnText = $columnText->getPlainText(); + if ($cellText instanceof PHPExcel_RichText) { + $cellText = $cellText->getPlainText(); } - // Only measure the part before the first newline character (is always "\n") - if (strpos($columnText, "\n") !== false) { - $columnText = substr($columnText, 0, strpos($columnText, "\n")); + // Special case if there are one or more newline characters ("\n") + if (strpos($cellText, "\n") !== false) { + $lineTexts = explode("\n", $cellText); + $lineWitdhs = array(); + foreach ($lineTexts as $lineText) { + $lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont); + } + return max($lineWidths); // width of longest line in cell } // Try to get the exact text width in pixels @@ -270,14 +263,14 @@ class PHPExcel_Shared_Font } // Width of text in pixels excl. padding - $columnWidth = self::getTextWidthPixelsExact($columnText, $font, $rotation); + $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation); // Excel adds some padding, use 1.07 of the width of an 'n' glyph $columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding } catch (Exception $e) { // Width of text in pixels excl. padding, approximation - $columnWidth = self::getTextWidthPixelsApprox($columnText, $font, $rotation); + $columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation); // Excel adds some padding, just use approx width of 'n' glyph $columnWidth += self::getTextWidthPixelsApprox('n', $font, 0); @@ -318,7 +311,7 @@ class PHPExcel_Shared_Font $upperRightCornerY = $textBox[5]; $upperLeftCornerX = $textBox[6]; $upperLeftCornerY = $textBox[7]; - + // Consider the rotation when calculating the width $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); @@ -391,7 +384,7 @@ class PHPExcel_Shared_Font public static function fontSizeToPixels($fontSizeInPoints = 11) { return (int) ((4 / 3) * $fontSizeInPoints); } - + /** * Calculate an (approximate) pixel size, based on inch size * @@ -401,7 +394,7 @@ class PHPExcel_Shared_Font public static function inchSizeToPixels($sizeInInch = 1) { return ($sizeInInch * 96); } - + /** * Calculate an (approximate) pixel size, based on centimeter size * @@ -431,34 +424,34 @@ class PHPExcel_Shared_Font switch ($name) { case 'Arial': $fontFile = ( - $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD) + $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD) : ($italic ? self::ARIAL_ITALIC : self::ARIAL) ); break; case 'Calibri': $fontFile = ( - $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD) + $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD) : ($italic ? self::CALIBRI_ITALIC : self::CALIBRI) ); break; case 'Courier New': $fontFile = ( - $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD) + $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD) : ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW) ); break; case 'Comic Sans MS': $fontFile = ( - $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS + $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS ); break; case 'Georgia': $fontFile = ( - $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD) + $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD) : ($italic ? self::GEORGIA_ITALIC : self::GEORGIA) ); break; @@ -469,7 +462,7 @@ class PHPExcel_Shared_Font case 'Liberation Sans': $fontFile = ( - $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD) + $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD) : ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS) ); break; @@ -488,7 +481,7 @@ class PHPExcel_Shared_Font case 'Palatino Linotype': $fontFile = ( - $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD) + $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD) : ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE) ); break; @@ -499,27 +492,27 @@ class PHPExcel_Shared_Font case 'Tahoma': $fontFile = ( - $bold ? self::TAHOMA_BOLD : self::TAHOMA + $bold ? self::TAHOMA_BOLD : self::TAHOMA ); break; case 'Times New Roman': $fontFile = ( - $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD) + $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD) : ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN) ); break; case 'Trebuchet MS': $fontFile = ( - $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD) + $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD) : ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS) ); break; case 'Verdana': $fontFile = ( - $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD) + $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD) : ($italic ? self::VERDANA_ITALIC : self::VERDANA) ); break; @@ -589,7 +582,7 @@ class PHPExcel_Shared_Font return $columnWidth; } - + /** * Get the effective row height for rows without a row dimension or rows with height -1 * For example, for Calibri 11 this is 15 points diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php index 49659d03c..c168567a3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php @@ -12,6 +12,13 @@ if (!defined('PHPEXCEL_ROOT')) { * @ignore */ define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + PHPExcel_Autoloader::Register(); + PHPExcel_Shared_ZipStreamWrapper::register(); + // check mbstring.func_overload + if (ini_get('mbstring.func_overload') & 2) { + throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + } } require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/utils/Error.php'; @@ -764,11 +771,11 @@ class Matrix { for($j = 0; $j < $this->n; ++$j) { $validValues = True; $value = $M->get($i, $j); - if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { $this->A[$i][$j] = trim($this->A[$i][$j],'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); } - if ((is_string($value)) && (!is_numeric($value))) { + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { $value = trim($value,'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); } @@ -850,11 +857,11 @@ class Matrix { for($j = 0; $j < $this->n; ++$j) { $validValues = True; $value = $M->get($i, $j); - if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { $this->A[$i][$j] = trim($this->A[$i][$j],'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); } - if ((is_string($value)) && (!is_numeric($value))) { + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { $value = trim($value,'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); } @@ -938,11 +945,11 @@ class Matrix { for($j = 0; $j < $this->n; ++$j) { $validValues = True; $value = $M->get($i, $j); - if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { $this->A[$i][$j] = trim($this->A[$i][$j],'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); } - if ((is_string($value)) && (!is_numeric($value))) { + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { $value = trim($value,'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); } @@ -989,11 +996,11 @@ class Matrix { for($j = 0; $j < $this->n; ++$j) { $validValues = True; $value = $M->get($i, $j); - if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { $this->A[$i][$j] = trim($this->A[$i][$j],'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); } - if ((is_string($value)) && (!is_numeric($value))) { + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { $value = trim($value,'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); } @@ -1246,11 +1253,11 @@ class Matrix { for($j = 0; $j < $this->n; ++$j) { $validValues = True; $value = $M->get($i, $j); - if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { $this->A[$i][$j] = trim($this->A[$i][$j],'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); } - if ((is_string($value)) && (!is_numeric($value))) { + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { $value = trim($value,'"'); $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); } diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE.php b/libraries/PHPExcel/PHPExcel/Shared/OLE.php index f65c24fad..a7cc9c3d8 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLE.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE.php @@ -19,19 +19,6 @@ // // $Id: OLE.php,v 1.13 2007/03/07 14:38:25 schmidt Exp $ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE.php'; -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_PPS.php'; -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_File.php'; -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_Root.php'; -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/ChainedBlockStream.php'; /** * Array for storing OLE instances that are accessed from @@ -527,20 +514,9 @@ class PHPExcel_Shared_OLE // factor used for separating numbers into 4 bytes parts $factor = pow(2,32); - $high_part = 0; - for ($i = 0; $i < 4; ++$i) { - list(, $high_part) = unpack('C', $string{(7 - $i)}); - if ($i < 3) { - $high_part *= 0x100; - } - } - $low_part = 0; - for ($i = 4; $i < 8; ++$i) { - list(, $low_part) = unpack('C', $string{(7 - $i)}); - if ($i < 7) { - $low_part *= 0x100; - } - } + list(, $high_part) = unpack('V', substr($string, 4, 4)); + list(, $low_part) = unpack('V', substr($string, 0, 4)); + $big_date = ($high_part * $factor) + $low_part; // translate to seconds $big_date /= 10000000; diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php index df96995c8..0da02c955 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,19 +22,9 @@ * @package PHPExcel_Shared_OLE * @copyright Copyright (c) 2006 - 2007 Christian Schmidt * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE.php'; - /** * PHPExcel_Shared_OLE_ChainedBlockStream * diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS.php new file mode 100644 index 000000000..aa1a4265c --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS.php @@ -0,0 +1,218 @@ + | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: PPS.php,v 1.7 2007/02/13 21:00:42 schmidt Exp $ + + +/** +* Class for creating PPS's for OLE containers +* +* @author Xavier Noguer +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE_PPS +{ + /** + * The PPS index + * @var integer + */ + public $No; + + /** + * The PPS name (in Unicode) + * @var string + */ + public $Name; + + /** + * The PPS type. Dir, Root or File + * @var integer + */ + public $Type; + + /** + * The index of the previous PPS + * @var integer + */ + public $PrevPps; + + /** + * The index of the next PPS + * @var integer + */ + public $NextPps; + + /** + * The index of it's first child if this is a Dir or Root PPS + * @var integer + */ + public $DirPps; + + /** + * A timestamp + * @var integer + */ + public $Time1st; + + /** + * A timestamp + * @var integer + */ + public $Time2nd; + + /** + * Starting block (small or big) for this PPS's data inside the container + * @var integer + */ + public $_StartBlock; + + /** + * The size of the PPS's data (in bytes) + * @var integer + */ + public $Size; + + /** + * The PPS's data (only used if it's not using a temporary file) + * @var string + */ + public $_data; + + /** + * Array of child PPS's (only used by Root and Dir PPS's) + * @var array + */ + public $children = array(); + + /** + * Pointer to OLE container + * @var OLE + */ + public $ole; + + /** + * The constructor + * + * @access public + * @param integer $No The PPS index + * @param string $name The PPS name + * @param integer $type The PPS type. Dir, Root or File + * @param integer $prev The index of the previous PPS + * @param integer $next The index of the next PPS + * @param integer $dir The index of it's first child if this is a Dir or Root PPS + * @param integer $time_1st A timestamp + * @param integer $time_2nd A timestamp + * @param string $data The (usually binary) source data of the PPS + * @param array $children Array containing children PPS for this PPS + */ + public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children) + { + $this->No = $No; + $this->Name = $name; + $this->Type = $type; + $this->PrevPps = $prev; + $this->NextPps = $next; + $this->DirPps = $dir; + $this->Time1st = $time_1st; + $this->Time2nd = $time_2nd; + $this->_data = $data; + $this->children = $children; + if ($data != '') { + $this->Size = strlen($data); + } else { + $this->Size = 0; + } + } + + /** + * Returns the amount of data saved for this PPS + * + * @access public + * @return integer The amount of data (in bytes) + */ + public function _DataLen() + { + if (!isset($this->_data)) { + return 0; + } + //if (isset($this->_PPS_FILE)) { + // fseek($this->_PPS_FILE, 0); + // $stats = fstat($this->_PPS_FILE); + // return $stats[7]; + //} else { + return strlen($this->_data); + //} + } + + /** + * Returns a string with the PPS's WK (What is a WK?) + * + * @access public + * @return string The binary string + */ + public function _getPpsWk() + { + $ret = $this->Name; + for ($i = 0; $i < (64 - strlen($this->Name)); ++$i) { + $ret .= "\x00"; + } + $ret .= pack("v", strlen($this->Name) + 2) // 66 + . pack("c", $this->Type) // 67 + . pack("c", 0x00) //UK // 68 + . pack("V", $this->PrevPps) //Prev // 72 + . pack("V", $this->NextPps) //Next // 76 + . pack("V", $this->DirPps) //Dir // 80 + . "\x00\x09\x02\x00" // 84 + . "\x00\x00\x00\x00" // 88 + . "\xc0\x00\x00\x00" // 92 + . "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root + . "\x00\x00\x00\x00" // 100 + . PHPExcel_Shared_OLE::LocalDate2OLE($this->Time1st) // 108 + . PHPExcel_Shared_OLE::LocalDate2OLE($this->Time2nd) // 116 + . pack("V", isset($this->_StartBlock)? + $this->_StartBlock:0) // 120 + . pack("V", $this->Size) // 124 + . pack("V", 0); // 128 + return $ret; + } + + /** + * Updates index and pointers to previous, next and children PPS's for this + * PPS. I don't think it'll work with Dir PPS's. + * + * @access public + * @param array &$pps_array Reference to the array of PPS's for the whole OLE + * container + * @return integer The index for this PPS + */ + public function _savePpsSetPnt(&$pps_array) + { + $pps_array[count($pps_array)] = &$this; + $this->No = count($pps_array) - 1; + $this->PrevPps = 0xFFFFFFFF; + $this->NextPps = 0xFFFFFFFF; + if (count($this->children) > 0) { + $this->DirPps = $this->children[0]->_savePpsSetPnt($pps_array); + } else { + $this->DirPps = 0xFFFFFFFF; + } + return $this->No; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/File.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/File.php new file mode 100644 index 000000000..f061f568c --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/File.php @@ -0,0 +1,84 @@ + | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: File.php,v 1.11 2007/02/13 21:00:42 schmidt Exp $ + + +/** +* Class for creating File PPS's for OLE containers +* +* @author Xavier Noguer +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE_PPS_File extends PHPExcel_Shared_OLE_PPS + { + /** + * The constructor + * + * @access public + * @param string $name The name of the file (in Unicode) + * @see OLE::Asc2Ucs() + */ + public function __construct($name) + { + parent::__construct( + null, + $name, + PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE, + null, + null, + null, + null, + null, + '', + array()); + } + + /** + * Initialization method. Has to be called right after OLE_PPS_File(). + * + * @access public + * @return mixed true on success + */ + public function init() + { + return true; + } + + /** + * Append data to PPS + * + * @access public + * @param string $data The data to append + */ + public function append($data) + { + $this->_data .= $data; + } + + /** + * Returns a stream for reading this file using fread() etc. + * @return resource a read-only stream + */ + public function getStream() + { + $this->ole->getStream($this); + } +} diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php new file mode 100644 index 000000000..a7f003509 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php @@ -0,0 +1,447 @@ + | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: Root.php,v 1.9 2005/04/23 21:53:49 dufuz Exp $ + + +/** +* Class for creating Root PPS's for OLE containers +* +* @author Xavier Noguer +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS + { + /** + * @param integer $time_1st A timestamp + * @param integer $time_2nd A timestamp + */ + public function __construct($time_1st, $time_2nd, $raChild) + { + parent::__construct( + null, + PHPExcel_Shared_OLE::Asc2Ucs('Root Entry'), + PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT, + null, + null, + null, + $time_1st, + $time_2nd, + null, + $raChild); + } + + /** + * Method for saving the whole OLE container (including files). + * In fact, if called with an empty argument (or '-'), it saves to a + * temporary file and then outputs it's contents to stdout. + * If a resource pointer to a stream created by fopen() is passed + * it will be used, but you have to close such stream by yourself. + * + * @param string|resource $filename The name of the file or stream where to save the OLE container. + * @access public + * @return mixed true on success + */ + public function save($filename) + { + // Initial Setting for saving + $this->_BIG_BLOCK_SIZE = pow(2, + ((isset($this->_BIG_BLOCK_SIZE))? $this->_adjust2($this->_BIG_BLOCK_SIZE) : 9)); + $this->_SMALL_BLOCK_SIZE= pow(2, + ((isset($this->_SMALL_BLOCK_SIZE))? $this->_adjust2($this->_SMALL_BLOCK_SIZE): 6)); + + if (is_resource($filename)) { + $this->_FILEH_ = $filename; + } else { + $this->_FILEH_ = fopen($filename, "wb"); + } + if ($this->_FILEH_ == false) { + throw new Exception("Can't open $filename. It may be in use or protected."); + } + // Make an array of PPS's (for Save) + $aList = array(); + $this->_savePpsSetPnt($aList); + // calculate values for header + list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo); + // Save Header + $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt); + + // Make Small Data string (write SBD) + $this->_data = $this->_makeSmallData($aList); + + // Write BB + $this->_saveBigData($iSBDcnt, $aList); + // Write PPS + $this->_savePps($aList); + // Write Big Block Depot and BDList and Adding Header informations + $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt); + + if (!is_resource($filename)) { + fclose($this->_FILEH_); + } + + return true; + } + + /** + * Calculate some numbers + * + * @access public + * @param array $raList Reference to an array of PPS's + * @return array The array of numbers + */ + public function _calcSize(&$raList) + { + // Calculate Basic Setting + list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0); + $iSmallLen = 0; + $iSBcnt = 0; + for ($i = 0; $i < count($raList); ++$i) { + if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { + $raList[$i]->Size = $raList[$i]->_DataLen(); + if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { + $iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); + } else { + $iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0)); + } + } + } + $iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE; + $iSlCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); + $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0); + $iBBcnt += (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) + + (( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0)); + $iCnt = count($raList); + $iBdCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; + $iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0)); + + return array($iSBDcnt, $iBBcnt, $iPPScnt); + } + + /** + * Helper function for caculating a magic value for block sizes + * + * @access public + * @param integer $i2 The argument + * @see save() + * @return integer + */ + public function _adjust2($i2) + { + $iWk = log($i2)/log(2); + return ($iWk > floor($iWk))? floor($iWk)+1:$iWk; + } + + /** + * Save OLE header + * + * @access public + * @param integer $iSBDcnt + * @param integer $iBBcnt + * @param integer $iPPScnt + */ + public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt) + { + $FILE = $this->_FILEH_; + + // Calculate Basic Setting + $iBlCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + + $iBdExL = 0; + $iAll = $iBBcnt + $iPPScnt + $iSBDcnt; + $iAllW = $iAll; + $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); + $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); + + // Calculate BD count + if ($iBdCnt > $i1stBdL) { + while (1) { + ++$iBdExL; + ++$iAllW; + $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); + $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); + if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) { + break; + } + } + } + + // Save Header + fwrite($FILE, + "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . pack("v", 0x3b) + . pack("v", 0x03) + . pack("v", -2) + . pack("v", 9) + . pack("v", 6) + . pack("v", 0) + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . pack("V", $iBdCnt) + . pack("V", $iBBcnt+$iSBDcnt) //ROOT START + . pack("V", 0) + . pack("V", 0x1000) + . pack("V", $iSBDcnt ? 0 : -2) //Small Block Depot + . pack("V", $iSBDcnt) + ); + // Extra BDList Start, Count + if ($iBdCnt < $i1stBdL) { + fwrite($FILE, + pack("V", -2). // Extra BDList Start + pack("V", 0) // Extra BDList Count + ); + } else { + fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL)); + } + + // BDList + for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) { + fwrite($FILE, pack("V", $iAll+$i)); + } + if ($i < $i1stBdL) { + for ($j = 0; $j < ($i1stBdL-$i); ++$j) { + fwrite($FILE, (pack("V", -1))); + } + } + } + + /** + * Saving big data (PPS's with data bigger than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) + * + * @access public + * @param integer $iStBlk + * @param array &$raList Reference to array of PPS's + */ + public function _saveBigData($iStBlk, &$raList) + { + $FILE = $this->_FILEH_; + + // cycle through PPS's + for ($i = 0; $i < count($raList); ++$i) { + if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) { + $raList[$i]->Size = $raList[$i]->_DataLen(); + if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) || + (($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) + { + // Write Data + //if (isset($raList[$i]->_PPS_FILE)) { + // $iLen = 0; + // fseek($raList[$i]->_PPS_FILE, 0); // To The Top + // while($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) { + // $iLen += strlen($sBuff); + // fwrite($FILE, $sBuff); + // } + //} else { + fwrite($FILE, $raList[$i]->_data); + //} + + if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) { + for ($j = 0; $j < ($this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)); ++$j) { + fwrite($FILE, "\x00"); + } + } + // Set For PPS + $raList[$i]->_StartBlock = $iStBlk; + $iStBlk += + (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0)); + } + // Close file for each PPS, and unlink it + //if (isset($raList[$i]->_PPS_FILE)) { + // fclose($raList[$i]->_PPS_FILE); + // $raList[$i]->_PPS_FILE = null; + // unlink($raList[$i]->_tmp_filename); + //} + } + } + } + + /** + * get small data (PPS's with data smaller than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) + * + * @access public + * @param array &$raList Reference to array of PPS's + */ + public function _makeSmallData(&$raList) + { + $sRes = ''; + $FILE = $this->_FILEH_; + $iSmBlk = 0; + + for ($i = 0; $i < count($raList); ++$i) { + // Make SBD, small data string + if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { + if ($raList[$i]->Size <= 0) { + continue; + } + if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { + $iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); + // Add to SBD + for ($j = 0; $j < ($iSmbCnt-1); ++$j) { + fwrite($FILE, pack("V", $j+$iSmBlk+1)); + } + fwrite($FILE, pack("V", -2)); + + //// Add to Data String(this will be written for RootEntry) + //if ($raList[$i]->_PPS_FILE) { + // fseek($raList[$i]->_PPS_FILE, 0); // To The Top + // while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) { + // $sRes .= $sBuff; + // } + //} else { + $sRes .= $raList[$i]->_data; + //} + if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) { + for ($j = 0; $j < ($this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); ++$j) { + $sRes .= "\x00"; + } + } + // Set for PPS + $raList[$i]->_StartBlock = $iSmBlk; + $iSmBlk += $iSmbCnt; + } + } + } + $iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); + if ($iSmBlk % $iSbCnt) { + for ($i = 0; $i < ($iSbCnt - ($iSmBlk % $iSbCnt)); ++$i) { + fwrite($FILE, pack("V", -1)); + } + } + return $sRes; + } + + /** + * Saves all the PPS's WKs + * + * @access public + * @param array $raList Reference to an array with all PPS's + */ + public function _savePps(&$raList) + { + // Save each PPS WK + for ($i = 0; $i < count($raList); ++$i) { + fwrite($this->_FILEH_, $raList[$i]->_getPpsWk()); + } + // Adjust for Block + $iCnt = count($raList); + $iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; + if ($iCnt % $iBCnt) { + for ($i = 0; $i < (($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE); ++$i) { + fwrite($this->_FILEH_, "\x00"); + } + } + } + + /** + * Saving Big Block Depot + * + * @access public + * @param integer $iSbdSize + * @param integer $iBsize + * @param integer $iPpsCnt + */ + public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt) + { + $FILE = $this->_FILEH_; + // Calculate Basic Setting + $iBbCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + + $iBdExL = 0; + $iAll = $iBsize + $iPpsCnt + $iSbdSize; + $iAllW = $iAll; + $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); + $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0); + // Calculate BD count + if ($iBdCnt >$i1stBdL) { + while (1) { + ++$iBdExL; + ++$iAllW; + $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); + $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0); + if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) { + break; + } + } + } + + // Making BD + // Set for SBD + if ($iSbdSize > 0) { + for ($i = 0; $i < ($iSbdSize - 1); ++$i) { + fwrite($FILE, pack("V", $i+1)); + } + fwrite($FILE, pack("V", -2)); + } + // Set for B + for ($i = 0; $i < ($iBsize - 1); ++$i) { + fwrite($FILE, pack("V", $i+$iSbdSize+1)); + } + fwrite($FILE, pack("V", -2)); + + // Set for PPS + for ($i = 0; $i < ($iPpsCnt - 1); ++$i) { + fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1)); + } + fwrite($FILE, pack("V", -2)); + // Set for BBD itself ( 0xFFFFFFFD : BBD) + for ($i = 0; $i < $iBdCnt; ++$i) { + fwrite($FILE, pack("V", 0xFFFFFFFD)); + } + // Set for ExtraBDList + for ($i = 0; $i < $iBdExL; ++$i) { + fwrite($FILE, pack("V", 0xFFFFFFFC)); + } + // Adjust for Block + if (($iAllW + $iBdCnt) % $iBbCnt) { + for ($i = 0; $i < ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); ++$i) { + fwrite($FILE, pack("V", -1)); + } + } + // Extra BDList + if ($iBdCnt > $i1stBdL) { + $iN=0; + $iNb=0; + for ($i = $i1stBdL;$i < $iBdCnt; $i++, ++$iN) { + if ($iN >= ($iBbCnt - 1)) { + $iN = 0; + ++$iNb; + fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb)); + } + fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i)); + } + if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) { + for ($i = 0; $i < (($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1))); ++$i) { + fwrite($FILE, pack("V", -1)); + } + } + fwrite($FILE, pack("V", -2)); + } + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLERead.php b/libraries/PHPExcel/PHPExcel/Shared/OLERead.php index 46cb5ade3..609fe4ba7 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLERead.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLERead.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); @@ -213,6 +213,58 @@ class PHPExcel_Shared_OLERead { } } + /** + * Extract binary stream data, summary information + * + * @return string|null + */ + public function getSummaryInformation() + { + if (!isset($this->summaryInformation)) { + return null; + } + + if ($this->props[$this->summaryInformation]['size'] < self::SMALL_BLOCK_THRESHOLD){ + $rootdata = $this->_readData($this->props[$this->rootentry]['startBlock']); + + $streamData = ''; + $block = $this->props[$this->summaryInformation]['startBlock']; + + $pos = 0; + while ($block != -2) { + $pos = $block * self::SMALL_BLOCK_SIZE; + $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); + + $block = $this->smallBlockChain[$block]; + } + + return $streamData; + + + } else { + $numBlocks = $this->props[$this->summaryInformation]['size'] / self::BIG_BLOCK_SIZE; + if ($this->props[$this->summaryInformation]['size'] % self::BIG_BLOCK_SIZE != 0) { + ++$numBlocks; + } + + if ($numBlocks == 0) return ''; + + + $streamData = ''; + $block = $this->props[$this->summaryInformation]['startBlock']; + + $pos = 0; + + while ($block != -2) { + $pos = ($block + 1) * self::BIG_BLOCK_SIZE; + $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); + $block = $this->bigBlockChain[$block]; + } + + return $streamData; + } + } + /** * Read a standard stream (by joining sectors using information from SAT) * @@ -280,6 +332,11 @@ class PHPExcel_Shared_OLERead { $this->rootentry = count($this->props) - 1; } + // Summary information + if ($name == chr(5) . 'SummaryInformation') { + $this->summaryInformation = count($this->props) - 1; + } + $offset += self::PROPERTY_STORAGE_BLOCK_SIZE; } diff --git a/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php b/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php index 1a5c11a33..441a4e105 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php +++ b/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/String.php b/libraries/PHPExcel/PHPExcel/Shared/String.php index bdd8b3faf..c3761fe95 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/String.php +++ b/libraries/PHPExcel/PHPExcel/Shared/String.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -48,6 +48,13 @@ class PHPExcel_Shared_String */ private static $_controlCharacters = array(); + /** + * SYLK Characters array + * + * $var array + */ + private static $_SYLKCharacters = array(); + /** * Decimal separator * @@ -89,6 +96,171 @@ class PHPExcel_Shared_String } } + /** + * Build SYLK characters array + */ + private static function _buildSYLKCharacters() + { + self::$_SYLKCharacters = array( + "\x1B 0" => chr(0), + "\x1B 1" => chr(1), + "\x1B 2" => chr(2), + "\x1B 3" => chr(3), + "\x1B 4" => chr(4), + "\x1B 5" => chr(5), + "\x1B 6" => chr(6), + "\x1B 7" => chr(7), + "\x1B 8" => chr(8), + "\x1B 9" => chr(9), + "\x1B :" => chr(10), + "\x1B ;" => chr(11), + "\x1B <" => chr(12), + "\x1B :" => chr(13), + "\x1B >" => chr(14), + "\x1B ?" => chr(15), + "\x1B!0" => chr(16), + "\x1B!1" => chr(17), + "\x1B!2" => chr(18), + "\x1B!3" => chr(19), + "\x1B!4" => chr(20), + "\x1B!5" => chr(21), + "\x1B!6" => chr(22), + "\x1B!7" => chr(23), + "\x1B!8" => chr(24), + "\x1B!9" => chr(25), + "\x1B!:" => chr(26), + "\x1B!;" => chr(27), + "\x1B!<" => chr(28), + "\x1B!=" => chr(29), + "\x1B!>" => chr(30), + "\x1B!?" => chr(31), + "\x1B'?" => chr(127), + "\x1B(0" => '€', // 128 in CP1252 + "\x1B(2" => '‚', // 130 in CP1252 + "\x1B(3" => 'Æ’', // 131 in CP1252 + "\x1B(4" => '„', // 132 in CP1252 + "\x1B(5" => '…', // 133 in CP1252 + "\x1B(6" => '†', // 134 in CP1252 + "\x1B(7" => '‡', // 135 in CP1252 + "\x1B(8" => 'ˆ', // 136 in CP1252 + "\x1B(9" => '‰', // 137 in CP1252 + "\x1B(:" => 'Å ', // 138 in CP1252 + "\x1B(;" => '‹', // 139 in CP1252 + "\x1BNj" => 'Å’', // 140 in CP1252 + "\x1B(>" => 'Ž', // 142 in CP1252 + "\x1B)1" => '‘', // 145 in CP1252 + "\x1B)2" => '’', // 146 in CP1252 + "\x1B)3" => '“', // 147 in CP1252 + "\x1B)4" => 'â€', // 148 in CP1252 + "\x1B)5" => '•', // 149 in CP1252 + "\x1B)6" => '–', // 150 in CP1252 + "\x1B)7" => '—', // 151 in CP1252 + "\x1B)8" => 'Ëœ', // 152 in CP1252 + "\x1B)9" => 'â„¢', // 153 in CP1252 + "\x1B):" => 'Å¡', // 154 in CP1252 + "\x1B);" => '›', // 155 in CP1252 + "\x1BNz" => 'Å“', // 156 in CP1252 + "\x1B)>" => 'ž', // 158 in CP1252 + "\x1B)?" => 'Ÿ', // 159 in CP1252 + "\x1B*0" => ' ', // 160 in CP1252 + "\x1BN!" => '¡', // 161 in CP1252 + "\x1BN\"" => '¢', // 162 in CP1252 + "\x1BN#" => '£', // 163 in CP1252 + "\x1BN(" => '¤', // 164 in CP1252 + "\x1BN%" => 'Â¥', // 165 in CP1252 + "\x1B*6" => '¦', // 166 in CP1252 + "\x1BN'" => '§', // 167 in CP1252 + "\x1BNH " => '¨', // 168 in CP1252 + "\x1BNS" => '©', // 169 in CP1252 + "\x1BNc" => 'ª', // 170 in CP1252 + "\x1BN+" => '«', // 171 in CP1252 + "\x1B*<" => '¬', // 172 in CP1252 + "\x1B*=" => '­', // 173 in CP1252 + "\x1BNR" => '®', // 174 in CP1252 + "\x1B*?" => '¯', // 175 in CP1252 + "\x1BN0" => '°', // 176 in CP1252 + "\x1BN1" => '±', // 177 in CP1252 + "\x1BN2" => '²', // 178 in CP1252 + "\x1BN3" => '³', // 179 in CP1252 + "\x1BNB " => '´', // 180 in CP1252 + "\x1BN5" => 'µ', // 181 in CP1252 + "\x1BN6" => '¶', // 182 in CP1252 + "\x1BN7" => '·', // 183 in CP1252 + "\x1B+8" => '¸', // 184 in CP1252 + "\x1BNQ" => '¹', // 185 in CP1252 + "\x1BNk" => 'º', // 186 in CP1252 + "\x1BN;" => '»', // 187 in CP1252 + "\x1BN<" => '¼', // 188 in CP1252 + "\x1BN=" => '½', // 189 in CP1252 + "\x1BN>" => '¾', // 190 in CP1252 + "\x1BN?" => '¿', // 191 in CP1252 + "\x1BNAA" => 'À', // 192 in CP1252 + "\x1BNBA" => 'Ã', // 193 in CP1252 + "\x1BNCA" => 'Â', // 194 in CP1252 + "\x1BNDA" => 'Ã', // 195 in CP1252 + "\x1BNHA" => 'Ä', // 196 in CP1252 + "\x1BNJA" => 'Ã…', // 197 in CP1252 + "\x1BNa" => 'Æ', // 198 in CP1252 + "\x1BNKC" => 'Ç', // 199 in CP1252 + "\x1BNAE" => 'È', // 200 in CP1252 + "\x1BNBE" => 'É', // 201 in CP1252 + "\x1BNCE" => 'Ê', // 202 in CP1252 + "\x1BNHE" => 'Ë', // 203 in CP1252 + "\x1BNAI" => 'ÃŒ', // 204 in CP1252 + "\x1BNBI" => 'Ã', // 205 in CP1252 + "\x1BNCI" => 'ÃŽ', // 206 in CP1252 + "\x1BNHI" => 'Ã', // 207 in CP1252 + "\x1BNb" => 'Ã', // 208 in CP1252 + "\x1BNDN" => 'Ñ', // 209 in CP1252 + "\x1BNAO" => 'Ã’', // 210 in CP1252 + "\x1BNBO" => 'Ó', // 211 in CP1252 + "\x1BNCO" => 'Ô', // 212 in CP1252 + "\x1BNDO" => 'Õ', // 213 in CP1252 + "\x1BNHO" => 'Ö', // 214 in CP1252 + "\x1B-7" => '×', // 215 in CP1252 + "\x1BNi" => 'Ø', // 216 in CP1252 + "\x1BNAU" => 'Ù', // 217 in CP1252 + "\x1BNBU" => 'Ú', // 218 in CP1252 + "\x1BNCU" => 'Û', // 219 in CP1252 + "\x1BNHU" => 'Ü', // 220 in CP1252 + "\x1B-=" => 'Ã', // 221 in CP1252 + "\x1BNl" => 'Þ', // 222 in CP1252 + "\x1BN{" => 'ß', // 223 in CP1252 + "\x1BNAa" => 'à', // 224 in CP1252 + "\x1BNBa" => 'á', // 225 in CP1252 + "\x1BNCa" => 'â', // 226 in CP1252 + "\x1BNDa" => 'ã', // 227 in CP1252 + "\x1BNHa" => 'ä', // 228 in CP1252 + "\x1BNJa" => 'Ã¥', // 229 in CP1252 + "\x1BNq" => 'æ', // 230 in CP1252 + "\x1BNKc" => 'ç', // 231 in CP1252 + "\x1BNAe" => 'è', // 232 in CP1252 + "\x1BNBe" => 'é', // 233 in CP1252 + "\x1BNCe" => 'ê', // 234 in CP1252 + "\x1BNHe" => 'ë', // 235 in CP1252 + "\x1BNAi" => 'ì', // 236 in CP1252 + "\x1BNBi" => 'í', // 237 in CP1252 + "\x1BNCi" => 'î', // 238 in CP1252 + "\x1BNHi" => 'ï', // 239 in CP1252 + "\x1BNs" => 'ð', // 240 in CP1252 + "\x1BNDn" => 'ñ', // 241 in CP1252 + "\x1BNAo" => 'ò', // 242 in CP1252 + "\x1BNBo" => 'ó', // 243 in CP1252 + "\x1BNCo" => 'ô', // 244 in CP1252 + "\x1BNDo" => 'õ', // 245 in CP1252 + "\x1BNHo" => 'ö', // 246 in CP1252 + "\x1B/7" => '÷', // 247 in CP1252 + "\x1BNy" => 'ø', // 248 in CP1252 + "\x1BNAu" => 'ù', // 249 in CP1252 + "\x1BNBu" => 'ú', // 250 in CP1252 + "\x1BNCu" => 'û', // 251 in CP1252 + "\x1BNHu" => 'ü', // 252 in CP1252 + "\x1B/=" => 'ý', // 253 in CP1252 + "\x1BN|" => 'þ', // 254 in CP1252 + "\x1BNHy" => 'ÿ', // 255 in CP1252 + ); + } + /** * Get whether mbstring extension is available * @@ -117,25 +289,37 @@ class PHPExcel_Shared_String return self::$_isIconvEnabled; } - // Check that iconv exists - // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false, - // we cannot use iconv when that happens - // Also, sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 - // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) - // CUSTOM: IBM AIX iconv() does not work - if (function_exists('iconv') - && @iconv('UTF-8', 'UTF-16LE', 'x') - && @iconv_substr('A', 0, 1, 'UTF-8') - && !(defined('PHP_OS') && @stristr(PHP_OS, 'AIX') - && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) - && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0))) { - - self::$_isIconvEnabled = true; - } else { + // Fail if iconv doesn't exist + if (!function_exists('iconv')) { self::$_isIconvEnabled = false; + return false; } - return self::$_isIconvEnabled; + // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false, + if (!@iconv('UTF-8', 'UTF-16LE', 'x')) { + self::$_isIconvEnabled = false; + return false; + } + + // Sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 + // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) + if (!@iconv('UTF-8', 'UTF-16LE', 'x')) { + self::$_isIconvEnabled = false; + return false; + } + + // CUSTOM: IBM AIX iconv() does not work + if ( defined('PHP_OS') && @stristr(PHP_OS, 'AIX') + && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) + && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0) ) + { + self::$_isIconvEnabled = false; + return false; + } + + // If we reach here no problems were detected with iconv + self::$_isIconvEnabled = true; + return true; } /** @@ -281,7 +465,7 @@ class PHPExcel_Shared_String } /** - * Convert string from one encoding to another. First try mbstring, then iconv, or no convertion + * Convert string from one encoding to another. First try iconv, then mbstring, or no convertion * * @param string $value * @param string $to Encoding to convert to, e.g. 'UTF-8' @@ -299,10 +483,45 @@ class PHPExcel_Shared_String $value = mb_convert_encoding($value, $to, $from); return $value; } - + if($from == 'UTF-16LE'){ + return self::utf16_decode($value, false); + }else if($from == 'UTF-16BE'){ + return self::utf16_decode($value); + } // else, no conversion return $value; } + + /** + * Decode UTF-16 encoded strings. + * + * Can handle both BOM'ed data and un-BOM'ed data. + * Assumes Big-Endian byte order if no BOM is available. + * This function was taken from http://php.net/manual/en/function.utf8-decode.php + * and $bom_be parameter added. + * + * @param string $str UTF-16 encoded data to decode. + * @return string UTF-8 / ISO encoded data. + * @access public + * @version 0.2 / 2010-05-13 + * @author Rasmus Andersson {@link http://rasmusandersson.se/} + * @author vadik56 + */ + function utf16_decode( $str, $bom_be=true ) { + if( strlen($str) < 2 ) return $str; + $c0 = ord($str{0}); + $c1 = ord($str{1}); + if( $c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); } + elseif( $c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; } + $len = strlen($str); + $newstr = ''; + for($i=0;$i<$len;$i+=2) { + if( $bom_be ) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); } + else { $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); } + $newstr .= ($val == 0x228) ? "\n" : chr($val); + } + return $newstr; + } /** * Get character count. First try mbstring, then iconv, finally strlen @@ -431,4 +650,28 @@ class PHPExcel_Shared_String self::$_thousandsSeparator = $pValue; } + /** + * Convert SYLK encoded string to UTF-8 + * + * @param string $pValue + * @return string UTF-8 encoded string + */ + public static function SYLKtoUTF8($pValue = '') + { + // If there is no escape character in the string there is nothing to do + if (strpos($pValue, '') === false) { + return $pValue; + } + + if(empty(self::$_SYLKCharacters)) { + self::_buildSYLKCharacters(); + } + + foreach (self::$_SYLKCharacters as $k => $v) { + $pValue = str_replace($k, $v, $pValue); + } + + return $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php b/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php index 4cd3d726a..9d43211da 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php +++ b/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ if (!defined('DATE_W3C')) { diff --git a/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php b/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php index b5bc1cb02..1c41ec69e 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php +++ b/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php @@ -22,14 +22,10 @@ * @package PHPExcel_Shared * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** Register new zip wrapper */ -PHPExcel_Shared_ZipStreamWrapper::register(); - - /** * PHPExcel_Shared_ZipStreamWrapper * @@ -83,24 +79,9 @@ class PHPExcel_Shared_ZipStreamWrapper { throw new Exception('Mode ' . $mode . ' is not supported. Only read mode is supported.'); } - // Parse URL - $url = @parse_url(str_replace('zip://', 'file://', $path)); - - // Fix URL - if (!is_array($url)) { - $url['host'] = substr($path, strlen('zip://')); - $url['path'] = ''; - } - if (strpos($url['host'], '#') !== false) { - if (!isset($url['fragment'])) { - $url['fragment'] = substr($url['host'], strpos($url['host'], '#') + 1) . $url['path']; - $url['host'] = substr($url['host'], 0, strpos($url['host'], '#')); - unset($url['path']); - } - } else { - $url['host'] = $url['host'] . $url['path']; - unset($url['path']); - } + $pos = strrpos($path, '#'); + $url['host'] = substr($path, 6, $pos - 6); // 6: strlen('zip://') + $url['fragment'] = substr($path, $pos + 1); // Open archive $this->_archive = new ZipArchive(); diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php index bd96d5827..7f9d01e3f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_Best_Fit * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php index 1d7212d9d..efc19987d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php @@ -22,18 +22,10 @@ * @package PHPExcel_Shared_Best_Fit * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php index 265048196..63222cb2c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php @@ -22,18 +22,10 @@ * @package PHPExcel_Shared_Best_Fit * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php index 115c78d0d..56d6ca9bd 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php @@ -22,18 +22,10 @@ * @package PHPExcel_Shared_Best_Fit * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php index dca14ff3c..e5e57c5b3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php @@ -22,18 +22,10 @@ * @package PHPExcel_Shared_Best_Fit * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php index 651aec2fe..c3b98d313 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php @@ -22,18 +22,10 @@ * @package PHPExcel_Shared_Best_Fit * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/trendClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/trendClass.php index 12ae7c6ac..f987831cd 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/trendClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/trendClass.php @@ -1,13 +1,5 @@ _parent = $parent; return $this; } - + /** * Is this a supervisor or a real style component? * @@ -258,7 +223,7 @@ class PHPExcel_Style implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->applyFromArray( * array( @@ -289,9 +254,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * ) * ); * - * + * * @param array $pStyles Array containing style information - * @param boolean $pAdvanced Advanced mode for setting borders. + * @param boolean $pAdvanced Advanced mode for setting borders. * @throws Exception * @return PHPExcel_Style */ @@ -373,7 +338,7 @@ class PHPExcel_Style implements PHPExcel_IComparable // loop through up to 3 x 3 = 9 regions for ($x = 1; $x <= $xMax; ++$x) { // start column index for region - $colStart = ($x == 3) ? + $colStart = ($x == 3) ? PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); @@ -417,7 +382,7 @@ class PHPExcel_Style implements PHPExcel_IComparable // build range for region $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; - + // retrieve relevant style array for region $regionStyles = $pStyles; unset($regionStyles['borders']['inside']); @@ -503,7 +468,7 @@ class PHPExcel_Style implements PHPExcel_IComparable $style = $workbook->getCellXfByIndex($oldXfIndex); $newStyle = clone $style; $newStyle->applyFromArray($pStyles); - + if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { // there is already such cell Xf in our collection $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); @@ -579,7 +544,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getFill() { return $this->_fill; } - + /** * Get Font * @@ -609,7 +574,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getBorders() { return $this->_borders; } - + /** * Get Alignment * @@ -618,7 +583,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getAlignment() { return $this->_alignment; } - + /** * Get Number Format * @@ -627,7 +592,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getNumberFormat() { return $this->_numberFormat; } - + /** * Get Conditional Styles. Only used on supervisor. * @@ -636,7 +601,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getConditionalStyles() { return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); } - + /** * Set Conditional Styles. Only used on supervisor. * @@ -651,7 +616,7 @@ class PHPExcel_Style implements PHPExcel_IComparable } return $this; } - + /** * Get Protection * @@ -660,18 +625,18 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getProtection() { return $this->_protection; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { $hashConditionals = ''; foreach ($this->_conditionalStyles as $conditional) { $hashConditionals .= $conditional->getHashCode(); } - + return md5( $this->getFill()->getHashCode() . $this->getFont()->getHashCode() @@ -683,7 +648,7 @@ class PHPExcel_Style implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Get own index in style collection * diff --git a/libraries/PHPExcel/PHPExcel/Style/Alignment.php b/libraries/PHPExcel/PHPExcel/Style/Alignment.php index fa52e0869..c248433d5 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Alignment.php +++ b/libraries/PHPExcel/PHPExcel/Style/Alignment.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Alignment * @@ -46,7 +34,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Alignment implements PHPExcel_IComparable -{ +{ /* Horizontal alignment styles */ const HORIZONTAL_GENERAL = 'general'; const HORIZONTAL_LEFT = 'left'; @@ -54,55 +42,55 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable const HORIZONTAL_CENTER = 'center'; const HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous'; const HORIZONTAL_JUSTIFY = 'justify'; - + /* Vertical alignment styles */ const VERTICAL_BOTTOM = 'bottom'; const VERTICAL_TOP = 'top'; const VERTICAL_CENTER = 'center'; const VERTICAL_JUSTIFY = 'justify'; - + /** * Horizontal * * @var string */ private $_horizontal; - + /** * Vertical * * @var string */ private $_vertical; - + /** * Text rotation * * @var int */ private $_textRotation; - + /** * Wrap text * * @var boolean */ private $_wrapText; - + /** * Shrink to fit * * @var boolean */ private $_shrinkToFit; - + /** * Indent - only possible with horizontal alignment left and right * * @var int */ private $_indent; - + /** * Parent Borders * @@ -219,7 +207,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getAlignment()->applyFromArray( * array( @@ -230,7 +218,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * ) * ); * - * + * * @param array $pStyles Array containing style information * @throws Exception * @return PHPExcel_Style_Alignment @@ -264,7 +252,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this; } - + /** * Get Horizontal * @@ -276,7 +264,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this->_horizontal; } - + /** * Set Horizontal * @@ -287,7 +275,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ($pValue == '') { $pValue = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; } - + if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('horizontal' => $pValue)); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -297,7 +285,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this; } - + /** * Get Vertical * @@ -309,7 +297,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this->_vertical; } - + /** * Set Vertical * @@ -320,7 +308,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ($pValue == '') { $pValue = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; } - + if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('vertical' => $pValue)); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -329,7 +317,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this; } - + /** * Get TextRotation * @@ -341,7 +329,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this->_textRotation; } - + /** * Set TextRotation * @@ -366,10 +354,10 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } else { throw new Exception("Text rotation should be a value between -90 and 90."); } - + return $this; } - + /** * Get Wrap Text * @@ -381,7 +369,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this->_wrapText; } - + /** * Set Wrap Text * @@ -400,7 +388,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this; } - + /** * Get Shrink to fit * @@ -412,7 +400,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this->_shrinkToFit; } - + /** * Set Shrink to fit * @@ -443,7 +431,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this->_indent; } - + /** * Set indent * @@ -464,12 +452,12 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } return $this; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashCode(); @@ -484,7 +472,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Border.php b/libraries/PHPExcel/PHPExcel/Style/Border.php index edaeaf301..b0335906c 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Border.php +++ b/libraries/PHPExcel/PHPExcel/Style/Border.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,25 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Border * @@ -65,17 +50,17 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable const BORDER_SLANTDASHDOT = 'slantDashDot'; const BORDER_THICK = 'thick'; const BORDER_THIN = 'thin'; - + /** * Border style * * @var string */ private $_borderStyle; - + /** * Border color - * + * * @var PHPExcel_Style_Color */ private $_color; @@ -132,7 +117,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable $this->_parentPropertyName = $parentPropertyName; return $this; } - + /** * Is this a supervisor or a real style component? * @@ -270,7 +255,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getBorders()->getTop()->applyFromArray( * array( @@ -281,7 +266,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * ) * ); * - * + * * @param array $pStyles Array containing style information * @throws Exception * @return PHPExcel_Style_Border @@ -303,7 +288,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable } return $this; } - + /** * Get Border style * @@ -315,7 +300,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable } return $this->_borderStyle; } - + /** * Set Border style * @@ -323,7 +308,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * @return PHPExcel_Style_Border */ public function setBorderStyle($pValue = PHPExcel_Style_Border::BORDER_NONE) { - + if ($pValue == '') { $pValue = PHPExcel_Style_Border::BORDER_NONE; } @@ -335,7 +320,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable } return $this; } - + /** * Get Border Color * @@ -344,7 +329,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable public function getColor() { return $this->_color; } - + /** * Set Border Color * @@ -355,7 +340,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable public function setColor(PHPExcel_Style_Color $pValue = null) { // make sure parameter is a real color and not a supervisor $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; - + if ($this->_isSupervisor) { $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -364,12 +349,12 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable } return $this; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashCode(); @@ -380,7 +365,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Borders.php b/libraries/PHPExcel/PHPExcel/Style/Borders.php index 4a6b3460b..d7a259a71 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Borders.php +++ b/libraries/PHPExcel/PHPExcel/Style/Borders.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,25 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Style_Border */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Border.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Borders * @@ -55,84 +40,84 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable const DIAGONAL_UP = 1; const DIAGONAL_DOWN = 2; const DIAGONAL_BOTH = 3; - + /** * Left * * @var PHPExcel_Style_Border */ private $_left; - + /** * Right * * @var PHPExcel_Style_Border */ private $_right; - + /** * Top * * @var PHPExcel_Style_Border */ private $_top; - + /** * Bottom * * @var PHPExcel_Style_Border */ private $_bottom; - + /** * Diagonal * * @var PHPExcel_Style_Border */ private $_diagonal; - + /** * DiagonalDirection * * @var int */ private $_diagonalDirection; - + /** * All borders psedo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ private $_allBorders; - + /** * Outline psedo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ private $_outline; - + /** * Inside psedo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ private $_inside; - + /** * Vertical pseudo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ private $_vertical; - + /** * Horizontal pseudo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ private $_horizontal; - + /** * Parent Borders * @@ -271,7 +256,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getBorders()->applyFromArray( * array( @@ -302,7 +287,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * ) * ); * - * + * * @param array $pStyles Array containing style information * @throws Exception * @return PHPExcel_Style_Borders @@ -336,7 +321,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this; } - + /** * Get Left * @@ -345,7 +330,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable public function getLeft() { return $this->_left; } - + /** * Get Right * @@ -354,7 +339,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable public function getRight() { return $this->_right; } - + /** * Get Top * @@ -363,7 +348,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable public function getTop() { return $this->_top; } - + /** * Get Bottom * @@ -381,7 +366,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable public function getDiagonal() { return $this->_diagonal; } - + /** * Get AllBorders (pseudo-border). Only applies to supervisor. * @@ -394,7 +379,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this->_allBorders; } - + /** * Get Outline (pseudo-border). Only applies to supervisor. * @@ -407,7 +392,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this->_outline; } - + /** * Get Inside (pseudo-border). Only applies to supervisor. * @@ -420,7 +405,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this->_inside; } - + /** * Get Vertical (pseudo-border). Only applies to supervisor. * @@ -433,7 +418,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this->_vertical; } - + /** * Get Horizontal (pseudo-border). Only applies to supervisor. * @@ -446,7 +431,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this->_horizontal; } - + /** * Get DiagonalDirection * @@ -458,7 +443,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this->_diagonalDirection; } - + /** * Set DiagonalDirection * @@ -477,12 +462,12 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } return $this; } - + /** * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashcode(); @@ -497,7 +482,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Color.php b/libraries/PHPExcel/PHPExcel/Style/Color.php index e17595c0d..e48d4a6f2 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Color.php +++ b/libraries/PHPExcel/PHPExcel/Style/Color.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Color * @@ -58,14 +46,14 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable const COLOR_DARKGREEN = 'FF008000'; const COLOR_YELLOW = 'FFFFFF00'; const COLOR_DARKYELLOW = 'FF808000'; - + /** * Indexed colors array * * @var array */ private static $_indexedColors; - + /** * ARGB - Alpha RGB * @@ -96,7 +84,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable /** * Create a new PHPExcel_Style_Color - * + * * @param string $pARGB */ public function __construct($pARGB = PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor = false) @@ -107,7 +95,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable // Initialise values $this->_argb = $pARGB; } - + /** * Bind parent. Only used for supervisor * @@ -214,11 +202,11 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFont()->getColor()->applyFromArray( array('rgb' => '808080') ); * - * + * * @param array $pStyles Array containing style information * @throws Exception * @return PHPExcel_Style_Color @@ -240,7 +228,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } return $this; } - + /** * Get ARGB * @@ -252,7 +240,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } return $this->_argb; } - + /** * Set ARGB * @@ -271,7 +259,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } return $this; } - + /** * Get RGB * @@ -283,7 +271,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } return substr($this->_argb, 2); } - + /** * Set RGB * @@ -302,17 +290,17 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } return $this; } - + /** * Get indexed color - * + * * @param int $pIndex * @return PHPExcel_Style_Color */ public static function indexedColor($pIndex) { // Clean parameter $pIndex = intval($pIndex); - + // Indexed colors if (is_null(self::$_indexedColors)) { self::$_indexedColors = array(); @@ -381,11 +369,11 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable self::$_indexedColors[] = '00333399'; self::$_indexedColors[] = '00333333'; } - + if (array_key_exists($pIndex, self::$_indexedColors)) { return new PHPExcel_Style_Color(self::$_indexedColors[$pIndex]); } - + return new PHPExcel_Style_Color(); } @@ -393,7 +381,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashCode(); @@ -403,7 +391,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Conditional.php b/libraries/PHPExcel/PHPExcel/Style/Conditional.php index e0520c8ec..83ab52b71 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Conditional.php +++ b/libraries/PHPExcel/PHPExcel/Style/Conditional.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,25 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Style */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Conditional * @@ -55,7 +40,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable const CONDITION_CELLIS = 'cellIs'; const CONDITION_CONTAINSTEXT = 'containsText'; const CONDITION_EXPRESSION = 'expression'; - + /* Operator types */ const OPERATOR_NONE = ''; const OPERATOR_BEGINSWITH = 'beginsWith'; @@ -69,42 +54,42 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable const OPERATOR_CONTAINSTEXT = 'containsText'; const OPERATOR_NOTCONTAINS = 'notContains'; const OPERATOR_BETWEEN = 'between'; - + /** * Condition type * * @var int */ private $_conditionType; - + /** * Operator type * * @var int */ private $_operatorType; - + /** * Text * * @var string */ private $_text; - + /** * Condition * * @var string[] */ private $_condition = array(); - + /** * Style - * + * * @var PHPExcel_Style */ private $_style; - + /** * Create a new PHPExcel_Style_Conditional */ @@ -117,7 +102,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable $this->_condition = array(); $this->_style = new PHPExcel_Style(); } - + /** * Get Condition type * @@ -126,7 +111,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function getConditionType() { return $this->_conditionType; } - + /** * Set Condition type * @@ -137,7 +122,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable $this->_conditionType = $pValue; return $this; } - + /** * Get Operator type * @@ -146,7 +131,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function getOperatorType() { return $this->_operatorType; } - + /** * Set Operator type * @@ -157,7 +142,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable $this->_operatorType = $pValue; return $this; } - + /** * Get text * @@ -166,7 +151,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function getText() { return $this->_text; } - + /** * Set text * @@ -177,7 +162,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable $this->_text = $value; return $this; } - + /** * Get Condition * @@ -188,10 +173,10 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable if (isset($this->_condition[0])) { return $this->_condition[0]; } - + return ''; } - + /** * Set Condition * @@ -202,10 +187,10 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function setCondition($pValue = '') { if (!is_array($pValue)) $pValue = array($pValue); - + return $this->setConditions($pValue); } - + /** * Get Conditions * @@ -214,7 +199,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function getConditions() { return $this->_condition; } - + /** * Set Conditions * @@ -224,11 +209,11 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function setConditions($pValue) { if (!is_array($pValue)) $pValue = array($pValue); - + $this->_condition = $pValue; return $this; } - + /** * Add Condition * @@ -239,7 +224,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable $this->_condition[] = $pValue; return $this; } - + /** * Get Style * @@ -248,7 +233,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable public function getStyle() { return $this->_style; } - + /** * Set Style * @@ -265,7 +250,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_conditionType @@ -275,7 +260,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Fill.php b/libraries/PHPExcel/PHPExcel/Style/Fill.php index 2d5fbe102..ac8c75213 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Fill.php +++ b/libraries/PHPExcel/PHPExcel/Style/Fill.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,25 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Fill * @@ -79,28 +64,28 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * @var string */ private $_fillType; - + /** * Rotation * * @var double */ private $_rotation; - + /** * Start color - * + * * @var PHPExcel_Style_Color */ private $_startColor; - + /** * End color - * + * * @var PHPExcel_Style_Color */ private $_endColor; - + /** * Parent Borders * @@ -221,7 +206,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFill()->applyFromArray( * array( @@ -236,7 +221,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * ) * ); * - * + * * @param array $pStyles Array containing style information * @throws Exception * @return PHPExcel_Style_Fill @@ -267,7 +252,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } return $this; } - + /** * Get Fill Type * @@ -279,7 +264,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } return $this->_fillType; } - + /** * Set Fill Type * @@ -295,7 +280,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } return $this; } - + /** * Get Rotation * @@ -307,7 +292,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } return $this->_rotation; } - + /** * Set Rotation * @@ -323,7 +308,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } return $this; } - + /** * Get Start Color * @@ -332,7 +317,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function getStartColor() { return $this->_startColor; } - + /** * Set Start Color * @@ -343,7 +328,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function setStartColor(PHPExcel_Style_Color $pValue = null) { // make sure parameter is a real color and not a supervisor $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; - + if ($this->_isSupervisor) { $styleArray = $this->getStartColor()->getStyleArray(array('argb' => $color->getARGB())); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -352,7 +337,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } return $this; } - + /** * Get End Color * @@ -361,7 +346,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function getEndColor() { return $this->_endColor; } - + /** * Set End Color * @@ -372,7 +357,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function setEndColor(PHPExcel_Style_Color $pValue = null) { // make sure parameter is a real color and not a supervisor $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; - + if ($this->_isSupervisor) { $styleArray = $this->getEndColor()->getStyleArray(array('argb' => $color->getARGB())); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -386,7 +371,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashCode(); @@ -399,7 +384,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Font.php b/libraries/PHPExcel/PHPExcel/Style/Font.php index 2adaff11c..c415226e1 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Font.php +++ b/libraries/PHPExcel/PHPExcel/Style/Font.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,25 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Font * @@ -56,63 +41,63 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable const UNDERLINE_DOUBLEACCOUNTING = 'doubleAccounting'; const UNDERLINE_SINGLE = 'single'; const UNDERLINE_SINGLEACCOUNTING = 'singleAccounting'; - + /** * Name * * @var string */ private $_name; - + /** * Bold * * @var boolean */ private $_bold; - + /** * Italic * * @var boolean */ private $_italic; - + /** * Superscript * * @var boolean */ private $_superScript; - + /** * Subscript * * @var boolean */ private $_subScript; - + /** * Underline * * @var string */ private $_underline; - + /** * Strikethrough * * @var boolean */ private $_strikethrough; - + /** * Foreground color - * + * * @var PHPExcel_Style_Color */ - private $_color; - + private $_color; + /** * Parent Borders * @@ -179,7 +164,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable { return $this->_isSupervisor; } - + /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -236,7 +221,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable /** * Apply styles from array - * + * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFont()->applyFromArray( * array( @@ -251,7 +236,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * ) * ); * - * + * * @param array $pStyles Array containing style information * @throws Exception * @return PHPExcel_Style_Font @@ -294,7 +279,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get Name * @@ -306,7 +291,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_name; } - + /** * Set Name * @@ -325,7 +310,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get Size * @@ -337,7 +322,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_size; } - + /** * Set Size * @@ -356,7 +341,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get Bold * @@ -368,7 +353,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_bold; } - + /** * Set Bold * @@ -387,7 +372,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get Italic * @@ -399,7 +384,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_italic; } - + /** * Set Italic * @@ -418,7 +403,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get SuperScript * @@ -430,7 +415,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_superScript; } - + /** * Set SuperScript * @@ -450,7 +435,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get SubScript * @@ -462,7 +447,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_subScript; } - + /** * Set SubScript * @@ -482,7 +467,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get Underline * @@ -494,7 +479,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_underline; } - + /** * Set Underline * @@ -513,7 +498,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this; } - + /** * Get Striketrough * @@ -523,7 +508,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable public function getStriketrough() { return $this->getStrikethrough(); } - + /** * Set Striketrough * @@ -534,7 +519,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable public function setStriketrough($pValue = false) { return $this->setStrikethrough($pValue); } - + /** * Get Strikethrough * @@ -546,7 +531,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } return $this->_strikethrough; } - + /** * Set Strikethrough * @@ -574,7 +559,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable public function getColor() { return $this->_color; } - + /** * Set Color * @@ -585,7 +570,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable public function setColor(PHPExcel_Style_Color $pValue = null) { // make sure parameter is a real color and not a supervisor $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; - + if ($this->_isSupervisor) { $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -599,7 +584,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashCode(); @@ -617,7 +602,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php b/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php index 83a8fc967..f6a406d61 100644 --- a/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php +++ b/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php @@ -22,28 +22,10 @@ * @package PHPExcel_Style * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Calculation_Functions */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; - - /** * PHPExcel_Style_NumberFormat * @@ -143,17 +125,17 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable private $_parent; /** - * Create a new PHPExcel_Style_NumberFormat - */ - public function __construct($isSupervisor = false) - { - // Supervisor? + * Create a new PHPExcel_Style_NumberFormat + */ + public function __construct($isSupervisor = false) + { + // Supervisor? $this->_isSupervisor = $isSupervisor; - // Initialise values - $this->_formatCode = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; - $this->_builtInFormatCode = 0; - } + // Initialise values + $this->_formatCode = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + $this->_builtInFormatCode = 0; + } /** * Bind parent. Only used for supervisor @@ -230,22 +212,23 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable return array('numberformat' => $array); } - /** - * Apply styles from array - * - * - * $objPHPExcel->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray( - * array( - * 'code' => PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE - * ) - * ); - * - * - * @param array $pStyles Array containing style information - * @throws Exception - * @return PHPExcel_Style_NumberFormat - */ - public function applyFromArray($pStyles = null) { + /** + * Apply styles from array + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray( + * array( + * 'code' => PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE + * ) + * ); + * + * + * @param array $pStyles Array containing style information + * @throws Exception + * @return PHPExcel_Style_NumberFormat + */ + public function applyFromArray($pStyles = null) + { if (is_array($pStyles)) { if ($this->_isSupervisor) { $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); @@ -260,32 +243,34 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable return $this; } - /** - * Get Format Code - * - * @return string - */ - public function getFormatCode() { + /** + * Get Format Code + * + * @return string + */ + public function getFormatCode() + { if ($this->_isSupervisor) { return $this->getSharedComponent()->getFormatCode(); } - if ($this->_builtInFormatCode !== false) - { - return self::builtInFormatCode($this->_builtInFormatCode); - } - return $this->_formatCode; - } + if ($this->_builtInFormatCode !== false) + { + return self::builtInFormatCode($this->_builtInFormatCode); + } + return $this->_formatCode; + } - /** - * Set Format Code - * - * @param string $pValue - * @return PHPExcel_Style_NumberFormat - */ - public function setFormatCode($pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL) { - if ($pValue == '') { - $pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; - } + /** + * Set Format Code + * + * @param string $pValue + * @return PHPExcel_Style_NumberFormat + */ + public function setFormatCode($pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL) + { + if ($pValue == '') { + $pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('code' => $pValue)); $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); @@ -294,27 +279,29 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $this->_builtInFormatCode = self::builtInFormatCodeIndex($pValue); } return $this; - } + } /** - * Get Built-In Format Code - * - * @return int - */ - public function getBuiltInFormatCode() { + * Get Built-In Format Code + * + * @return int + */ + public function getBuiltInFormatCode() + { if ($this->_isSupervisor) { return $this->getSharedComponent()->getBuiltInFormatCode(); } - return $this->_builtInFormatCode; - } + return $this->_builtInFormatCode; + } - /** - * Set Built-In Format Code - * - * @param int $pValue - * @return PHPExcel_Style_NumberFormat - */ - public function setBuiltInFormatCode($pValue = 0) { + /** + * Set Built-In Format Code + * + * @param int $pValue + * @return PHPExcel_Style_NumberFormat + */ + public function setBuiltInFormatCode($pValue = 0) + { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('code' => self::builtInFormatCode($pValue))); @@ -324,15 +311,15 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $this->_formatCode = self::builtInFormatCode($pValue); } return $this; - } + } - /** - * Fill built-in format codes - */ - private static function fillBuiltInFormatCodes() - { - // Built-in format codes - if (is_null(self::$_builtInFormats)) { + /** + * Fill built-in format codes + */ + private static function fillBuiltInFormatCodes() + { + // Built-in format codes + if (is_null(self::$_builtInFormats)) { self::$_builtInFormats = array(); // General @@ -388,68 +375,72 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable // Flip array (for faster lookups) self::$_flippedBuiltInFormats = array_flip(self::$_builtInFormats); - } - } + } + } - /** - * Get built-in format code - * - * @param int $pIndex - * @return string - */ - public static function builtInFormatCode($pIndex) { - // Clean parameter + /** + * Get built-in format code + * + * @param int $pIndex + * @return string + */ + public static function builtInFormatCode($pIndex) + { + // Clean parameter $pIndex = intval($pIndex); // Ensure built-in format codes are available - self::fillBuiltInFormatCodes(); + self::fillBuiltInFormatCodes(); // Lookup format code if (array_key_exists($pIndex, self::$_builtInFormats)) { return self::$_builtInFormats[$pIndex]; } - return ''; - } + return ''; + } - /** - * Get built-in format code index - * - * @param string $formatCode - * @return int|boolean - */ - public static function builtInFormatCodeIndex($formatCode) { - // Ensure built-in format codes are available - self::fillBuiltInFormatCodes(); + /** + * Get built-in format code index + * + * @param string $formatCode + * @return int|boolean + */ + public static function builtInFormatCodeIndex($formatCode) + { + // Ensure built-in format codes are available + self::fillBuiltInFormatCodes(); // Lookup format code if (array_key_exists($formatCode, self::$_flippedBuiltInFormats)) { return self::$_flippedBuiltInFormats[$formatCode]; } - return false; - } + return false; + } /** * Get hash code * * @return string Hash code */ - public function getHashCode() { + public function getHashCode() + { if ($this->_isSupervisor) { return $this->getSharedComponent()->getHashCode(); } - return md5( - $this->_formatCode - . $this->_builtInFormatCode - . __CLASS__ - ); - } + return md5( + $this->_formatCode + . $this->_builtInFormatCode + . __CLASS__ + ); + } /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ - public function __clone() { + public function __clone() + { $vars = get_object_vars($this); foreach ($vars as $key => $value) { if (is_object($value)) { @@ -511,7 +502,8 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * @param array $callBack Callback function for additional formatting of string * @return string Formatted string */ - public static function toFormattedString($value = '', $format = '', $callBack = null) { + public static function toFormattedString($value = '', $format = '', $callBack = null) + { // For now we do not treat strings although section 4 of a format code affects strings if (!is_numeric($value)) return $value; @@ -587,7 +579,8 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $format = strtr($format,self::$_dateFormatReplacements12); } - $value = gmdate($format, PHPExcel_Shared_Date::ExcelToPHP($value)); + $dateObj = PHPExcel_Shared_Date::ExcelToPHPObject($value); + $value = $dateObj->format($format); } else if (preg_match('/%$/', $format)) { // % number format if ($format === self::FORMAT_PERCENTAGE) { @@ -606,31 +599,44 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable } } else { - if (preg_match ("/^([0-9.,-]+)$/", $value)) { - if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { - $value = 'EUR ' . sprintf('%1.2f', $value); + if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { + $value = 'EUR ' . sprintf('%1.2f', $value); - } else { - // In Excel formats, "_" is used to add spacing, which we can't do in HTML - $format = preg_replace('/_./', '', $format); + } else { + // In Excel formats, "_" is used to add spacing, which we can't do in HTML + $format = preg_replace('/_./', '', $format); - // Some non-number characters are escaped with \, which we don't need - $format = preg_replace("/\\\\/", '', $format); + // Some non-number characters are escaped with \, which we don't need + $format = preg_replace("/\\\\/", '', $format); - // Some non-number strings are quoted, so we'll get rid of the quotes - $format = preg_replace('/"/', '', $format); + // Some non-number strings are quoted, so we'll get rid of the quotes + $format = preg_replace('/"/', '', $format); - // TEMPORARY - Convert # to 0 - $format = preg_replace('/\\#/', '0', $format); + // Find out if we need thousands separator + // This is indicated by a comma enclosed by a digit placeholder: + // #,# or 0,0 + $useThousands = preg_match('/(#,#|0,0)/', $format); + if ($useThousands) { + $format = preg_replace('/0,0/', '00', $format); + $format = preg_replace('/#,#/', '##', $format); + } - // Find out if we need thousands separator - $useThousands = preg_match('/,/', $format); - if ($useThousands) { - $format = preg_replace('/,/', '', $format); - } + // Scale thousands, millions,... + // This is indicated by a number of commas after a digit placeholder: + // #, or 0.0,, + $scale = 1; // same as no scale + $matches = array(); + if (preg_match('/(#|0)(,+)/', $format, $matches)) { + $scale = pow(1000, strlen($matches[2])); - if (preg_match('/0?.*\?\/\?/', $format, $m)) { - //echo 'Format mask is fractional '.$format.'
'; + // strip the commas + $format = preg_replace('/0,+/', '0', $format); + $format = preg_replace('/#,+/', '#', $format); + } + + if (preg_match('/#?.*\?\/\?/', $format, $m)) { + //echo 'Format mask is fractional '.$format.'
'; + if ($value != (int)$value) { $sign = ($value < 0) ? '-' : ''; $integerPart = floor(abs($value)); @@ -650,28 +656,41 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; $value = "$sign$adjustedDecimalPart/$adjustedDecimalDivisor"; } + } - } else { - // Handle the number itself - $number_regex = "/(\d+)(\.?)(\d*)/"; - if (preg_match($number_regex, $format, $matches)) { - $left = $matches[1]; - $dec = $matches[2]; - $right = $matches[3]; - if ($useThousands) { - $value = number_format( - $value - , strlen($right) - , PHPExcel_Shared_String::getDecimalSeparator() - , PHPExcel_Shared_String::getThousandsSeparator() - ); + } else { + // Handle the number itself - } else { - $sprintf_pattern = "%1." . strlen($right) . "f"; - $value = sprintf($sprintf_pattern, $value); - } - $value = preg_replace($number_regex, $value, $format); + // scale number + $value = $value / $scale; + + // Strip # + $format = preg_replace('/\\#/', '', $format); + + $number_regex = "/(0+)(\.?)(0*)/"; + $matches = array(); + if (preg_match($number_regex, $format, $matches)) { + $left = $matches[1]; + $dec = $matches[2]; + $right = $matches[3]; + + // minimun width of formatted number (including dot) + $minWidth = strlen($left) + strlen($dec) + strlen($right); + + if ($useThousands) { + $value = number_format( + $value + , strlen($right) + , PHPExcel_Shared_String::getDecimalSeparator() + , PHPExcel_Shared_String::getThousandsSeparator() + ); + + } else { + $sprintf_pattern = "%0$minWidth." . strlen($right) . "f"; + $value = sprintf($sprintf_pattern, $value); } + + $value = preg_replace($number_regex, $value, $format); } } } @@ -685,4 +704,5 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable return $value; } + } diff --git a/libraries/PHPExcel/PHPExcel/Style/Protection.php b/libraries/PHPExcel/PHPExcel/Style/Protection.php index 12611d13b..1c7070200 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Protection.php +++ b/libraries/PHPExcel/PHPExcel/Style/Protection.php @@ -26,18 +26,6 @@ */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - - /** * PHPExcel_Style_Protection * @@ -276,7 +264,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet.php b/libraries/PHPExcel/PHPExcel/Worksheet.php index 74bd65266..74b70b756 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet.php @@ -22,94 +22,10 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Worksheet_RowDimension */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/RowDimension.php'; - -/** PHPExcel_Worksheet_ColumnDimension */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/ColumnDimension.php'; - -/** PHPExcel_Worksheet_PageSetup */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/PageSetup.php'; - -/** PHPExcel_Worksheet_PageMargins */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/PageMargins.php'; - -/** PHPExcel_Worksheet_HeaderFooter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooter.php'; - -/** PHPExcel_Worksheet_BaseDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php'; - -/** PHPExcel_Worksheet_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; - -/** PHPExcel_Worksheet_MemoryDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; - -/** PHPExcel_Worksheet_HeaderFooterDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; - -/** PHPExcel_Worksheet_SheetView */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/SheetView.php'; - -/** PHPExcel_Worksheet_Protection */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Protection.php'; - -/** PHPExcel_Worksheet_RowIterator */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/RowIterator.php'; - -/** PHPExcel_Comment */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Comment.php'; - -/** PHPExcel_Style */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; - -/** PHPExcel_Style_Fill */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Fill.php'; - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_Style_NumberFormat */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Shared_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_Shared_PasswordHasher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; - -/** PHPExcel_ReferenceHelper */ -require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; - - /** * PHPExcel_Worksheet * @@ -123,12 +39,19 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable const BREAK_NONE = 0; const BREAK_ROW = 1; const BREAK_COLUMN = 2; - + /* Sheet state */ const SHEETSTATE_VISIBLE = 'visible'; const SHEETSTATE_HIDDEN = 'hidden'; const SHEETSTATE_VERYHIDDEN = 'veryHidden'; + /** + * Invalid characters in sheet title + * + * @var array + */ + private static $_invalidCharacters = array('*', ':', '/', '\\', '?', '[', ']'); + /** * Parent spreadsheet * @@ -137,11 +60,11 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable private $_parent; /** - * Collection of cells + * Cacheable collection of cells * - * @var PHPExcel_Cell[] + * @var PHPExcel_CachedObjectStorage_xxx */ - private $_cellCollection = array(); + private $_cellCollection = null; /** * Collection of row dimensions @@ -184,7 +107,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @var string */ private $_title; - + /** * Sheet state * @@ -297,6 +220,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ private $_printGridlines = false; + /** + * Show row and column headers? + * + * @var boolean + */ + private $_showRowColHeaders = true; + /** * Show summary below? (Row/Column outline) * @@ -387,6 +317,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->setTitle($pTitle); $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); + $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); + // Set page setup $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); @@ -420,6 +352,35 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(null); } + + public function disconnectCells() { + $this->_cellCollection->unsetWorksheetCells(); + $this->_cellCollection = null; + + // detach ourself from the workbook, so that it can then delete this worksheet successfully + $this->_parent = null; + } + + /** + * Return the cache controller for the cell collection + * + * @return PHPExcel_CachedObjectStorage_xxx + */ + public function getCellCacheController() { + return $this->_cellCollection; + } // function getCellCacheController() + + + /** + * Get array of invalid characters for sheet title + * + * @return array + */ + public static function getInvalidCharacters() + { + return self::$_invalidCharacters; + } + /** * Check sheet title for valid Excel syntax * @@ -430,7 +391,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable private static function _checkSheetTitle($pValue) { // Some of the printable ASCII characters are invalid: * : / \ ? [ ] - if (preg_match('/(\\*|\\:|\\/|\\\\|\\?|\\[|\\])/', $pValue)) { + if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) { throw new Exception('Invalid character found in sheet title'); } @@ -455,7 +416,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->sortCellCollection(); } - return $this->_cellCollection; + if (is_null($this->_cellCollection)) { + return array(); + } + return $this->_cellCollection->getCellList(); } /** @@ -466,29 +430,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable public function sortCellCollection() { if (!$this->_cellCollectionIsSorted) { - // Re-order cell collection - // uasort($this->_cellCollection, array('PHPExcel_Cell', 'compareCells')); <-- slow - - $indexed = array(); - foreach (array_keys($this->_cellCollection) as $index) { - $rowNum = $this->_cellCollection[$index]->getRow(); - $colNum = PHPExcel_Cell::columnIndexFromString($this->_cellCollection[$index]->getColumn()); - - // Columns are limited to ZZZ (18278), so 20000 is plenty to assure no conflicts - $key = $rowNum * 20000 + $colNum; - - $indexed[$key] = $index; // &$this->_cellCollection[$index]; + if (!is_null($this->_cellCollection)) { + $this->_cellCollection->sortCellList(); } - ksort($indexed); - - // Rebuild cellCollection from the sorted index - $newCellCollection = array(); - foreach ($indexed as $index) { - $newCellCollection[$index] = $this->_cellCollection[$index]; - } - - $this->_cellCollection = $newCellCollection; - $this->_cellCollectionIsSorted = true; } return $this; @@ -610,31 +554,38 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } // There is only something to do if there are some auto-size columns - if (count($autoSizes) > 0) { - // loop though all cells in sheet expand $autoSizes - foreach ($this->getCellCollection(false) as $cell) { + if (!empty($autoSizes)) { + + // build list of cells references that participate in a merge + $isMergeCell = array(); + foreach ($this->getMergeCells() as $cells) { + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) { + $isMergeCell[$cellReference] = true; + } + } + + // loop through all cells in the worksheet + foreach ($this->getCellCollection(false) as $cellID) { + $cell = $this->getCell($cellID); if (isset($autoSizes[$cell->getColumn()])) { - // Calculated value - $cellValue = $cell->getCalculatedValue(); + // Determine width if cell does not participate in a merge + if (!isset($isMergeCell[$cell->getCoordinate()])) { + // Calculated value + $cellValue = $cell->getCalculatedValue(); - // To formatted string - $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()); + // To formatted string + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()); - foreach ($this->getMergeCells() as $cells) { - if ($cell->isInRange($cells) && !$calculateMergeCells) { - $cellValue = ''; // do not calculate merge cells - } + $autoSizes[$cell->getColumn()] = max( + (float)$autoSizes[$cell->getColumn()], + (float)PHPExcel_Shared_Font::calculateColumnWidth( + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $cellValue, + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getDefaultStyle()->getFont() + ) + ); } - - $autoSizes[$cell->getColumn()] = max( - (float)$autoSizes[$cell->getColumn()], - (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), - $cellValue, - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), - $this->getDefaultStyle()->getFont() - ) - ); } } @@ -730,7 +681,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this; } - + /** * Get sheet state * @@ -739,7 +690,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable public function getSheetState() { return $this->_sheetState; } - + /** * Set sheet state * @@ -750,7 +701,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_sheetState = $value; return $this; } - + /** * Get page setup * @@ -906,7 +857,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 0, $pValue = null) { - return $this->setCellValue(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pValue); + return $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValue($pValue); } /** @@ -935,7 +886,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 0, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING) { - return $this->setCellValueExplicit(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pValue, $pDataType); + return $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType); } /** @@ -948,8 +899,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable public function getCell($pCoordinate = 'A1') { // Check cell collection - if (isset($this->_cellCollection[$pCoordinate])) { - return $this->_cellCollection[$pCoordinate]; + if ($this->_cellCollection->isDataSet($pCoordinate)) { + return $this->_cellCollection->getCacheData($pCoordinate); } // Worksheet reference? @@ -964,16 +915,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); if (!is_null($namedRange)) { $pCoordinate = $namedRange->getRange(); - if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) { - if (!$namedRange->getLocalOnly()) { - return $namedRange->getWorksheet()->getCell($pCoordinate); - } else { - throw new Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); - } - } else { - //Allow named ranges within the same sheet. - return $this->getCell($pCoordinate); - } + return $namedRange->getWorksheet()->getCell($pCoordinate); } } @@ -990,7 +932,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Coordinates $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); - $this->_cellCollection[$pCoordinate] = new PHPExcel_Cell($aCoordinates[0], $aCoordinates[1], null, PHPExcel_Cell_DataType::TYPE_NULL, $this); + $cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell($aCoordinates[0], $aCoordinates[1], null, PHPExcel_Cell_DataType::TYPE_NULL, $this)); $this->_cellCollectionIsSorted = false; if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) @@ -1005,18 +947,16 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { // then there is a row dimension with explicit style, assign it to the cell - $this->_cellCollection[$pCoordinate]->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); - + $cell->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { // then there is a column dimension, assign it to the cell - $this->_cellCollection[$pCoordinate]->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); - + $cell->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); } else { // set to default index - $this->_cellCollection[$pCoordinate]->setXfIndex(0); + $cell->setXfIndex(0); } - return $this->_cellCollection[$pCoordinate]; + return $cell; } } @@ -1029,22 +969,23 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function getCellByColumnAndRow($pColumn = 0, $pRow = 0) { - $coordinate = PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow; + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); + $coordinate = $columnLetter . $pRow; - if (!isset($this->_cellCollection[$coordinate])) { - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); - - $this->_cellCollection[$coordinate] = new PHPExcel_Cell($columnLetter, $pRow, null, PHPExcel_Cell_DataType::TYPE_NULL, $this); + if (!$this->_cellCollection->isDataSet($coordinate)) { + $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell($columnLetter, $pRow, null, PHPExcel_Cell_DataType::TYPE_NULL, $this)); $this->_cellCollectionIsSorted = false; if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) - $this->_cachedHighestColumn = $pColumn; + $this->_cachedHighestColumn = $columnLetter; if ($this->_cachedHighestRow < $pRow) $this->_cachedHighestRow = $pRow; + + return $cell; } - return $this->_cellCollection[$coordinate]; + return $this->_cellCollection->getCacheData($coordinate); } /** @@ -1090,7 +1031,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); // Cell exists? - return isset($this->_cellCollection[$pCoordinate]); + return $this->_cellCollection->isDataSet($pCoordinate); } } @@ -1455,6 +1396,24 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if (strpos($pRange,':') !== false) { $this->_mergeCells[$pRange] = $pRange; + + // make sure cells are created + + // get the cells in the range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + + // create upper left cell if it does not already exist + $upperLeft = $aReferences[0]; + if (!$this->cellExists($upperLeft)) { + $this->getCell($upperLeft)->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } + + // create or blank out the rest of the cells in the range + $count = count($aReferences); + for ($i = 1; $i < $count; $i++) { + $this->getCell($aReferences[$i])->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } + } else { throw new Exception('Merge must be set on a range of cells.'); } @@ -1533,7 +1492,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * Set merge cells array for the entire sheet. Use instead mergeCells() to merge * a single cell range. * - * @param array + * @param array */ public function setMergeCells($pValue = array()) { @@ -1877,6 +1836,26 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this; } + /** + * Show row and column headers? + * + * @return boolean + */ + public function getShowRowColHeaders() { + return $this->_showRowColHeaders; + } + + /** + * Set show row and column headers + * + * @param boolean $pValue Show row and column headers (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowRowColHeaders($pValue = false) { + $this->_showRowColHeaders = $pValue; + return $this; + } + /** * Show summary below? (Row/Column outlining) * @@ -2083,7 +2062,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * Fill worksheet from values in array * * @param array $source Source array - * @param mixed $nullValue Value treated as "null" + * @param mixed $nullValue Value in source array that stands for blank cell * @throws Exception * @return PHPExcel_Worksheet */ @@ -2103,9 +2082,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable for ($i = 0; $i < $rowCount; ++$i) { if ($rowData[$i] != $nullValue) { // Set cell value - $this->setCellValue( - PHPExcel_Cell::stringFromColumnIndex($i + $startColumn) . $currentRow, $rowData[$i] - ); + $this->getCell(PHPExcel_Cell::stringFromColumnIndex($i + $startColumn) . $currentRow) + ->setValue($rowData[$i]); } } } @@ -2195,17 +2173,20 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $highestRow = 1; // Find cells that can be cleaned - foreach ($this->_cellCollection as $coordinate => $cell) { + foreach ($this->_cellCollection->getCellList() as $coordinate) { + $cell = $this->getCell($coordinate); // Can be cleaned? $canBeCleaned = false; - // Empty value? + /* Excel doesn't remove such empty cells + // Empty value? if (is_null($cell->getValue()) || (!is_object($cell->getValue()) && $cell->getValue() === '' && !$cell->hasHyperlink())) { // default style ? if ($cell->getXfIndex() == 0) { $canBeCleaned = true; } } + */ // Referenced in image? if (isset($imageCoordinates[$coordinate]) && $imageCoordinates[$coordinate] === true) { @@ -2215,7 +2196,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Clean? if ($canBeCleaned) { // Remove the cell - unset($this->_cellCollection[$coordinate]); + $this->_cellCollection->deleteCacheData($coordinate); } else { // Determine highest column and row if ($highestColumn < PHPExcel_Cell::columnIndexFromString($cell->getColumn())) { @@ -2319,8 +2300,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } // else create hyperlink - $cell = $this->getCell($pCellCoordinate); - $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink($cell); + $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink(); return $this->_hyperlinkCollection[$pCellCoordinate]; } @@ -2337,7 +2317,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable unset($this->_hyperlinkCollection[$pCellCoordinate]); } else { $this->_hyperlinkCollection[$pCellCoordinate] = $pHyperlink; - $pHyperlink->setParent($this->getCell($pCellCoordinate)); } return $this; } @@ -2376,8 +2355,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } // else create data validation - $cell = $this->getCell($pCellCoordinate); - $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation($cell); + $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation(); return $this->_dataValidationCollection[$pCellCoordinate]; } @@ -2394,7 +2372,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable unset($this->_dataValidationCollection[$pCellCoordinate]); } else { $this->_dataValidationCollection[$pCellCoordinate] = $pDataValidation; - $pDataValidation->setParent($this->getCell($pCellCoordinate)); } return $this; } @@ -2420,6 +2397,34 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this->_dataValidationCollection; } + /** + * Accepts a range, returning it as a range that falls within the current highest row and column of the worksheet + * + * @param string $range + * @return string Adjusted range value + */ + public function shrinkRangeToFit($range) { + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); + + $rangeBlocks = explode(' ',$range); + foreach ($rangeBlocks as &$rangeSet) { + $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($rangeSet); + + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[0][0]) > $maxCol) { $rangeBoundaries[0][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[0][1] > $maxRow) { $rangeBoundaries[0][1] = $maxRow; } + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[1][0]) > $maxCol) { $rangeBoundaries[1][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[1][1] > $maxRow) { $rangeBoundaries[1][1] = $maxRow; } + $rangeSet = $rangeBoundaries[0][0].$rangeBoundaries[0][1].':'.$rangeBoundaries[1][0].$rangeBoundaries[1][1]; + } + unset($rangeSet); + $stRange = implode(' ',$rangeBlocks); + + return $stRange; + } + + /** * Get tab color * diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php index 79f8c1611..efc04bcbd 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,27 +22,10 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Worksheet_Drawing_Shadow */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; - /** * PHPExcel_Worksheet_BaseDrawing * @@ -51,98 +34,98 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable -{ +{ /** * Image counter * * @var int */ private static $_imageCounter = 0; - + /** * Image index * * @var int */ private $_imageIndex = 0; - + /** * Name * * @var string */ protected $_name; - + /** * Description * * @var string */ protected $_description; - + /** * Worksheet * * @var PHPExcel_Worksheet */ protected $_worksheet; - + /** * Coordinates * * @var string */ protected $_coordinates; - + /** * Offset X * * @var int */ protected $_offsetX; - + /** * Offset Y * * @var int */ protected $_offsetY; - + /** * Width * * @var int */ protected $_width; - + /** * Height * * @var int */ protected $_height; - + /** * Proportional resize * * @var boolean */ protected $_resizeProportional; - + /** * Rotation * * @var int */ protected $_rotation; - + /** * Shadow * * @var PHPExcel_Worksheet_Drawing_Shadow */ - protected $_shadow; - + protected $_shadow; + /** * Create a new PHPExcel_Worksheet_BaseDrawing */ @@ -160,12 +143,12 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_resizeProportional = true; $this->_rotation = 0; $this->_shadow = new PHPExcel_Worksheet_Drawing_Shadow(); - + // Set image index self::$_imageCounter++; $this->_imageIndex = self::$_imageCounter; } - + /** * Get image index * @@ -174,7 +157,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getImageIndex() { return $this->_imageIndex; } - + /** * Get Name * @@ -183,7 +166,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getName() { return $this->_name; } - + /** * Set Name * @@ -194,7 +177,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_name = $pValue; return $this; } - + /** * Get Description * @@ -203,7 +186,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getDescription() { return $this->_description; } - + /** * Set Description * @@ -223,7 +206,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getWorksheet() { return $this->_worksheet; } - + /** * Set Worksheet * @@ -242,7 +225,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable if ($pOverrideOld) { // Remove drawing from old PHPExcel_Worksheet $iterator = $this->_worksheet->getDrawingCollection()->getIterator(); - + while ($iterator->valid()) { if ($iterator->current()->getHashCode() == $this->getHashCode()) { $this->_worksheet->getDrawingCollection()->offsetUnset( $iterator->key() ); @@ -250,7 +233,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable break; } } - + // Set new PHPExcel_Worksheet $this->setWorksheet($pValue); } else { @@ -259,7 +242,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable } return $this; } - + /** * Get Coordinates * @@ -267,8 +250,8 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable */ public function getCoordinates() { return $this->_coordinates; - } - + } + /** * Set Coordinates * @@ -279,7 +262,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_coordinates = $pValue; return $this; } - + /** * Get OffsetX * @@ -288,7 +271,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getOffsetX() { return $this->_offsetX; } - + /** * Set OffsetX * @@ -299,7 +282,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_offsetX = $pValue; return $this; } - + /** * Get OffsetY * @@ -308,7 +291,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getOffsetY() { return $this->_offsetY; } - + /** * Set OffsetY * @@ -319,7 +302,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_offsetY = $pValue; return $this; } - + /** * Get Width * @@ -328,7 +311,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getWidth() { return $this->_width; } - + /** * Set Width * @@ -338,16 +321,16 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function setWidth($pValue = 0) { // Resize proportional? if ($this->_resizeProportional && $pValue != 0) { - $ratio = $this->_height / $this->_width; + $ratio = $this->_height / $this->_width; $this->_height = round($ratio * $pValue); } - + // Set width $this->_width = $pValue; - + return $this; } - + /** * Get Height * @@ -356,7 +339,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getHeight() { return $this->_height; } - + /** * Set Height * @@ -366,16 +349,16 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function setHeight($pValue = 0) { // Resize proportional? if ($this->_resizeProportional && $pValue != 0) { - $ratio = $this->_width / $this->_height; + $ratio = $this->_width / $this->_height; $this->_width = round($ratio * $pValue); } - + // Set height $this->_height = $pValue; - + return $this; } - + /** * Set width and height with proportional resize * Example: @@ -403,7 +386,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable } return $this; } - + /** * Get ResizeProportional * @@ -412,7 +395,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getResizeProportional() { return $this->_resizeProportional; } - + /** * Set ResizeProportional * @@ -423,7 +406,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_resizeProportional = $pValue; return $this; } - + /** * Get Rotation * @@ -432,7 +415,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getRotation() { return $this->_rotation; } - + /** * Set Rotation * @@ -443,7 +426,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable $this->_rotation = $pValue; return $this; } - + /** * Get Shadow * @@ -452,7 +435,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable public function getShadow() { return $this->_shadow; } - + /** * Set Shadow * @@ -469,7 +452,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_name @@ -485,7 +468,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php b/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php index f0683e6e4..4786997b8 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php @@ -22,38 +22,20 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - - /** * PHPExcel_Worksheet_CellIterator - * + * * Used to iterate rows in a PHPExcel_Worksheet * * @category PHPExcel * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Worksheet_CellIterator extends IteratorIterator +class PHPExcel_Worksheet_CellIterator extends CachingIterator { /** * PHPExcel_Worksheet to iterate @@ -61,21 +43,21 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator * @var PHPExcel_Worksheet */ private $_subject; - + /** * Row index * * @var int */ private $_rowIndex; - + /** * Current iterator position * * @var int */ private $_position = 0; - + /** * Loop only existing cells * @@ -94,14 +76,14 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator $this->_subject = $subject; $this->_rowIndex = $rowIndex; } - + /** * Destructor */ public function __destruct() { unset($this->_subject); } - + /** * Rewind iterator */ @@ -158,7 +140,7 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator return $this->_position < $columnCount; } - + /** * Get loop only existing cells * @@ -167,7 +149,7 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator public function getIterateOnlyExistingCells() { return $this->_onlyExistingCells; } - + /** * Set loop only existing cells * diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php b/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php index 7b6810fbf..45233726c 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php @@ -22,7 +22,7 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php index e6f84e226..fcdece002 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,31 +22,10 @@ * @package PHPExcel_Worksheet_Drawing * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Worksheet_BaseDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php'; - -/** PHPExcel_Worksheet_Drawing_Shadow */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; - - /** * PHPExcel_Worksheet_Drawing * @@ -54,15 +33,15 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * @package PHPExcel_Worksheet_Drawing * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable -{ +class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable +{ /** * Path * * @var string */ private $_path; - + /** * Create a new PHPExcel_Worksheet_Drawing */ @@ -70,11 +49,11 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen { // Initialise values $this->_path = ''; - + // Initialize parent parent::__construct(); } - + /** * Get Filename * @@ -83,7 +62,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen public function getFilename() { return basename($this->_path); } - + /** * Get indexed filename (using image index) * @@ -94,7 +73,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen $fileName = str_replace(' ', '_', $fileName); return str_replace('.' . $this->getExtension(), '', $fileName) . $this->getImageIndex() . '.' . $this->getExtension(); } - + /** * Get Extension * @@ -104,7 +83,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen $exploded = explode(".", basename($this->_path)); return $exploded[count($exploded) - 1]; } - + /** * Get Path * @@ -113,7 +92,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen public function getPath() { return $this->_path; } - + /** * Set Path * @@ -126,7 +105,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen if ($pVerifyFile) { if (file_exists($pValue)) { $this->_path = $pValue; - + if ($this->_width == 0 && $this->_height == 0) { // Get width/height list($this->_width, $this->_height) = getimagesize($pValue); @@ -144,7 +123,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_path @@ -152,7 +131,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php index a294e5a0e..1ee8262c2 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,27 +22,10 @@ * @package PHPExcel_Worksheet_Drawing * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - /** * PHPExcel_Worksheet_Drawing_Shadow * @@ -51,7 +34,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable -{ +{ /* Shadow alignment */ const SHADOW_BOTTOM = 'b'; const SHADOW_BOTTOM_LEFT = 'bl'; @@ -60,7 +43,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable const SHADOW_LEFT = 'l'; const SHADOW_TOP = 't'; const SHADOW_TOP_LEFT = 'tl'; - const SHADOW_TOP_RIGHT = 'tr'; + const SHADOW_TOP_RIGHT = 'tr'; /** * Visible @@ -68,7 +51,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable * @var boolean */ private $_visible; - + /** * Blur radius * @@ -77,7 +60,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable * @var int */ private $_blurRadius; - + /** * Shadow distance * @@ -86,35 +69,35 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable * @var int */ private $_distance; - + /** * Shadow direction (in degrees) * * @var int */ private $_direction; - + /** * Shadow alignment * * @var int */ private $_alignment; - + /** * Color - * + * * @var PHPExcel_Style_Color */ private $_color; - + /** * Alpha * * @var int */ private $_alpha; - + /** * Create a new PHPExcel_Worksheet_Drawing_Shadow */ @@ -129,7 +112,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK); $this->_alpha = 50; } - + /** * Get Visible * @@ -138,7 +121,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getVisible() { return $this->_visible; } - + /** * Set Visible * @@ -149,7 +132,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_visible = $pValue; return $this; } - + /** * Get Blur radius * @@ -158,7 +141,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getBlurRadius() { return $this->_blurRadius; } - + /** * Set Blur radius * @@ -169,7 +152,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_blurRadius = $pValue; return $this; } - + /** * Get Shadow distance * @@ -178,7 +161,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getDistance() { return $this->_distance; } - + /** * Set Shadow distance * @@ -189,7 +172,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_distance = $pValue; return $this; } - + /** * Get Shadow direction (in degrees) * @@ -198,7 +181,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getDirection() { return $this->_direction; } - + /** * Set Shadow direction (in degrees) * @@ -209,7 +192,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_direction = $pValue; return $this; } - + /** * Get Shadow alignment * @@ -218,7 +201,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getAlignment() { return $this->_alignment; } - + /** * Set Shadow alignment * @@ -229,7 +212,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_alignment = $pValue; return $this; } - + /** * Get Color * @@ -238,7 +221,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getColor() { return $this->_color; } - + /** * Set Color * @@ -250,7 +233,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable $this->_color = $pValue; return $this; } - + /** * Get Alpha * @@ -259,7 +242,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable public function getAlpha() { return $this->_alpha; } - + /** * Set Alpha * @@ -275,7 +258,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( ($this->_visible ? 't' : 'f') @@ -288,7 +271,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php index ef60e77a9..eb33cc246 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Worksheet_HeaderFooterDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; - - /** * PHPExcel_Worksheet_HeaderFooter * @@ -46,14 +34,14 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; * * There are a number of formatting codes that can be written inline with the actual header / footer text, which * affect the formatting in the header or footer. - * + * * Example: This example shows the text "Center Bold Header" on the first line (center section), and the date on * the second line (center section). * &CCenter &"-,Bold"Bold&"-,Regular"Header_x000A_&D - * + * * General Rules: * There is no required order in which these codes must appear. - * + * * The first occurrence of the following codes turns the formatting ON, the second occurrence turns it OFF again: * - strikethrough * - superscript @@ -75,7 +63,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; * &Y - code for "text subscript" on / off * &C - code for "center section". When two or more occurrences of this section marker exist, the contents * from all markers are concatenated, in the order of appearance, and placed into the center section. - * + * * &D - code for "date" * &T - code for "time" * &G - code for "picture as background" @@ -106,7 +94,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooter -{ +{ /* Header/footer image location */ const IMAGE_HEADER_LEFT = 'LH'; const IMAGE_HEADER_CENTER = 'CH'; @@ -114,14 +102,14 @@ class PHPExcel_Worksheet_HeaderFooter const IMAGE_FOOTER_LEFT = 'LF'; const IMAGE_FOOTER_CENTER = 'CF'; const IMAGE_FOOTER_RIGHT = 'RF'; - + /** * OddHeader * * @var string */ private $_oddHeader; - + /** * OddFooter * @@ -135,7 +123,7 @@ class PHPExcel_Worksheet_HeaderFooter * @var string */ private $_evenHeader; - + /** * EvenFooter * @@ -149,42 +137,42 @@ class PHPExcel_Worksheet_HeaderFooter * @var string */ private $_firstHeader; - + /** * FirstFooter * * @var string */ private $_firstFooter; - + /** * Different header for Odd/Even, defaults to false * * @var boolean */ private $_differentOddEven; - + /** * Different header for first page, defaults to false * * @var boolean */ private $_differentFirst; - + /** * Scale with document, defaults to true * * @var boolean */ private $_scaleWithDocument; - + /** * Align with margins, defaults to true * * @var boolean */ private $_alignWithMargins; - + /** * Header/footer images * @@ -207,10 +195,10 @@ class PHPExcel_Worksheet_HeaderFooter $this->_differentOddEven = false; $this->_differentFirst = false; $this->_scaleWithDocument = true; - $this->_alignWithMargins = true; + $this->_alignWithMargins = true; $this->_headerFooterImages = array(); } - + /** * Get OddHeader * @@ -219,7 +207,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getOddHeader() { return $this->_oddHeader; } - + /** * Set OddHeader * @@ -230,7 +218,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_oddHeader = $pValue; return $this; } - + /** * Get OddFooter * @@ -239,7 +227,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getOddFooter() { return $this->_oddFooter; } - + /** * Set OddFooter * @@ -250,7 +238,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_oddFooter = $pValue; return $this; } - + /** * Get EvenHeader * @@ -259,7 +247,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getEvenHeader() { return $this->_evenHeader; } - + /** * Set EvenHeader * @@ -270,7 +258,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_evenHeader = $pValue; return $this; } - + /** * Get EvenFooter * @@ -279,7 +267,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getEvenFooter() { return $this->_evenFooter; } - + /** * Set EvenFooter * @@ -290,7 +278,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_evenFooter = $pValue; return $this; } - + /** * Get FirstHeader * @@ -299,7 +287,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getFirstHeader() { return $this->_firstHeader; } - + /** * Set FirstHeader * @@ -310,7 +298,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_firstHeader = $pValue; return $this; } - + /** * Get FirstFooter * @@ -319,7 +307,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getFirstFooter() { return $this->_firstFooter; } - + /** * Set FirstFooter * @@ -330,7 +318,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_firstFooter = $pValue; return $this; } - + /** * Get DifferentOddEven * @@ -339,7 +327,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getDifferentOddEven() { return $this->_differentOddEven; } - + /** * Set DifferentOddEven * @@ -350,7 +338,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_differentOddEven = $pValue; return $this; } - + /** * Get DifferentFirst * @@ -359,7 +347,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getDifferentFirst() { return $this->_differentFirst; } - + /** * Set DifferentFirst * @@ -370,7 +358,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_differentFirst = $pValue; return $this; } - + /** * Get ScaleWithDocument * @@ -379,7 +367,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getScaleWithDocument() { return $this->_scaleWithDocument; } - + /** * Set ScaleWithDocument * @@ -390,7 +378,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_scaleWithDocument = $pValue; return $this; } - + /** * Get AlignWithMargins * @@ -399,7 +387,7 @@ class PHPExcel_Worksheet_HeaderFooter public function getAlignWithMargins() { return $this->_alignWithMargins; } - + /** * Set AlignWithMargins * @@ -410,7 +398,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_alignWithMargins = $pValue; return $this; } - + /** * Add header/footer image * @@ -423,7 +411,7 @@ class PHPExcel_Worksheet_HeaderFooter $this->_headerFooterImages[$location] = $image; return $this; } - + /** * Remove header/footer image * @@ -437,7 +425,7 @@ class PHPExcel_Worksheet_HeaderFooter } return $this; } - + /** * Set header/footer images * @@ -449,11 +437,11 @@ class PHPExcel_Worksheet_HeaderFooter if (!is_array($images)) { throw new Exception('Invalid parameter!'); } - + $this->_headerFooterImages = $images; return $this; } - + /** * Get header/footer images * @@ -469,10 +457,10 @@ class PHPExcel_Worksheet_HeaderFooter if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_CENTER])) $images[self::IMAGE_FOOTER_CENTER] = $this->_headerFooterImages[self::IMAGE_FOOTER_CENTER]; if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_RIGHT])) $images[self::IMAGE_FOOTER_RIGHT] = $this->_headerFooterImages[self::IMAGE_FOOTER_RIGHT]; $this->_headerFooterImages = $images; - + return $this->_headerFooterImages; } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php index d3be4b75a..7ae8d18f6 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,31 +22,10 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Worksheet_BaseDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php'; - -/** PHPExcel_Worksheet_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; - - /** * PHPExcel_Worksheet_HeaderFooterDrawing * @@ -54,57 +33,57 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable -{ +class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable +{ /** * Path * * @var string */ private $_path; - + /** * Name * * @var string */ protected $_name; - + /** * Offset X * * @var int */ protected $_offsetX; - + /** * Offset Y * * @var int */ protected $_offsetY; - + /** * Width * * @var int */ protected $_width; - + /** * Height * * @var int */ protected $_height; - + /** * Proportional resize * * @var boolean */ protected $_resizeProportional; - + /** * Create a new PHPExcel_Worksheet_HeaderFooterDrawing */ @@ -119,7 +98,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing $this->_height = 0; $this->_resizeProportional = true; } - + /** * Get Name * @@ -128,7 +107,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getName() { return $this->_name; } - + /** * Set Name * @@ -139,7 +118,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing $this->_name = $pValue; return $this; } - + /** * Get OffsetX * @@ -148,7 +127,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getOffsetX() { return $this->_offsetX; } - + /** * Set OffsetX * @@ -159,7 +138,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing $this->_offsetX = $pValue; return $this; } - + /** * Get OffsetY * @@ -168,7 +147,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getOffsetY() { return $this->_offsetY; } - + /** * Set OffsetY * @@ -179,7 +158,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing $this->_offsetY = $pValue; return $this; } - + /** * Get Width * @@ -188,7 +167,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getWidth() { return $this->_width; } - + /** * Set Width * @@ -198,16 +177,16 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function setWidth($pValue = 0) { // Resize proportional? if ($this->_resizeProportional && $pValue != 0) { - $ratio = $this->_width / $this->_height; + $ratio = $this->_width / $this->_height; $this->_height = round($ratio * $pValue); } - + // Set width $this->_width = $pValue; - + return $this; } - + /** * Get Height * @@ -216,7 +195,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getHeight() { return $this->_height; } - + /** * Set Height * @@ -226,16 +205,16 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function setHeight($pValue = 0) { // Resize proportional? if ($this->_resizeProportional && $pValue != 0) { - $ratio = $this->_width / $this->_height; + $ratio = $this->_width / $this->_height; $this->_width = round($ratio * $pValue); } - + // Set height $this->_height = $pValue; - + return $this; } - + /** * Set width and height with proportional resize * Example: @@ -263,7 +242,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing } return $this; } - + /** * Get ResizeProportional * @@ -272,7 +251,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getResizeProportional() { return $this->_resizeProportional; } - + /** * Set ResizeProportional * @@ -283,7 +262,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing $this->_resizeProportional = $pValue; return $this; } - + /** * Get Filename * @@ -292,16 +271,17 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getFilename() { return basename($this->_path); } - + /** * Get Extension * * @return string */ public function getExtension() { - return end(explode(".", basename($this->_path))); + $parts = explode(".", basename($this->_path)); + return end($parts); } - + /** * Get Path * @@ -310,7 +290,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing public function getPath() { return $this->_path; } - + /** * Set Path * @@ -323,7 +303,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing if ($pVerifyFile) { if (file_exists($pValue)) { $this->_path = $pValue; - + if ($this->_width == 0 && $this->_height == 0) { // Get width/height list($this->_width, $this->_height) = getimagesize($pValue); @@ -341,7 +321,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_path @@ -353,7 +333,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php index 05a45dfee..cbc57504d 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,31 +22,10 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Worksheet_BaseDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php'; - -/** PHPExcel_Worksheet_Drawing_Shadow */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; - - /** * PHPExcel_Worksheet_MemoryDrawing * @@ -54,48 +33,48 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable -{ +class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable +{ /* Rendering functions */ const RENDERING_DEFAULT = 'imagepng'; const RENDERING_PNG = 'imagepng'; const RENDERING_GIF = 'imagegif'; const RENDERING_JPEG = 'imagejpeg'; - + /* MIME types */ const MIMETYPE_DEFAULT = 'image/png'; const MIMETYPE_PNG = 'image/png'; const MIMETYPE_GIF = 'image/gif'; const MIMETYPE_JPEG = 'image/jpeg'; - + /** * Image resource * * @var resource */ private $_imageResource; - + /** * Rendering function * * @var string */ private $_renderingFunction; - + /** * Mime type * * @var string */ private $_mimeType; - + /** * Unique name * * @var string */ private $_uniqueName; - + /** * Create a new PHPExcel_Worksheet_MemoryDrawing */ @@ -106,11 +85,11 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im $this->_renderingFunction = self::RENDERING_DEFAULT; $this->_mimeType = self::MIMETYPE_DEFAULT; $this->_uniqueName = md5(rand(0, 9999). time() . rand(0, 9999)); - + // Initialize parent parent::__construct(); } - + /** * Get image resource * @@ -119,7 +98,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im public function getImageResource() { return $this->_imageResource; } - + /** * Set image resource * @@ -128,7 +107,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im */ public function setImageResource($value = null) { $this->_imageResource = $value; - + if (!is_null($this->_imageResource)) { // Get width/height $this->_width = imagesx($this->_imageResource); @@ -136,7 +115,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im } return $this; } - + /** * Get rendering function * @@ -145,7 +124,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im public function getRenderingFunction() { return $this->_renderingFunction; } - + /** * Set rendering function * @@ -156,7 +135,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im $this->_renderingFunction = $value; return $this; } - + /** * Get mime type * @@ -165,7 +144,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im public function getMimeType() { return $this->_mimeType; } - + /** * Set mime type * @@ -176,7 +155,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im $this->_mimeType = $value; return $this; } - + /** * Get indexed filename (using image index) * @@ -186,7 +165,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im $extension = strtolower($this->getMimeType()); $extension = explode('/', $extension); $extension = $extension[1]; - + return $this->_uniqueName . $this->getImageIndex() . '.' . $extension; } @@ -194,7 +173,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im * Get hash code * * @return string Hash code - */ + */ public function getHashCode() { return md5( $this->_renderingFunction @@ -204,7 +183,7 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im . __CLASS__ ); } - + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php b/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php index 80ee4cfe0..eb9a91906 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php @@ -22,7 +22,7 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php b/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php index 1424fe062..f85f65e28 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php @@ -22,7 +22,7 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php b/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php index d87c208e0..3bbd692a1 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_Shared_PasswordHasher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; - - /** * PHPExcel_Worksheet_Protection * @@ -53,119 +41,119 @@ class PHPExcel_Worksheet_Protection * @var boolean */ private $_sheet; - + /** * Objects * * @var boolean */ private $_objects; - + /** * Scenarios * * @var boolean */ private $_scenarios; - + /** * Format cells * * @var boolean */ private $_formatCells; - + /** * Format columns * * @var boolean */ private $_formatColumns; - + /** * Format rows * * @var boolean */ private $_formatRows; - + /** * Insert columns * * @var boolean */ private $_insertColumns; - + /** * Insert rows * * @var boolean */ private $_insertRows; - + /** * Insert hyperlinks * * @var boolean */ private $_insertHyperlinks; - + /** * Delete columns * * @var boolean */ private $_deleteColumns; - + /** * Delete rows * * @var boolean */ private $_deleteRows; - + /** * Select locked cells * * @var boolean */ private $_selectLockedCells; - + /** * Sort * * @var boolean */ private $_sort; - + /** * AutoFilter * * @var boolean */ private $_autoFilter; - + /** * Pivot tables * * @var boolean */ private $_pivotTables; - + /** * Select unlocked cells * * @var boolean */ private $_selectUnlockedCells; - + /** * Password * * @var string */ private $_password; - + /** * Create a new PHPExcel_Worksheet_Protection */ @@ -214,7 +202,7 @@ class PHPExcel_Worksheet_Protection $this->_pivotTables || $this->_selectUnlockedCells; } - + /** * Get Sheet * @@ -223,7 +211,7 @@ class PHPExcel_Worksheet_Protection function getSheet() { return $this->_sheet; } - + /** * Set Sheet * @@ -243,7 +231,7 @@ class PHPExcel_Worksheet_Protection function getObjects() { return $this->_objects; } - + /** * Set Objects * @@ -263,7 +251,7 @@ class PHPExcel_Worksheet_Protection function getScenarios() { return $this->_scenarios; } - + /** * Set Scenarios * @@ -283,7 +271,7 @@ class PHPExcel_Worksheet_Protection function getFormatCells() { return $this->_formatCells; } - + /** * Set FormatCells * @@ -303,7 +291,7 @@ class PHPExcel_Worksheet_Protection function getFormatColumns() { return $this->_formatColumns; } - + /** * Set FormatColumns * @@ -323,7 +311,7 @@ class PHPExcel_Worksheet_Protection function getFormatRows() { return $this->_formatRows; } - + /** * Set FormatRows * @@ -343,7 +331,7 @@ class PHPExcel_Worksheet_Protection function getInsertColumns() { return $this->_insertColumns; } - + /** * Set InsertColumns * @@ -363,7 +351,7 @@ class PHPExcel_Worksheet_Protection function getInsertRows() { return $this->_insertRows; } - + /** * Set InsertRows * @@ -383,7 +371,7 @@ class PHPExcel_Worksheet_Protection function getInsertHyperlinks() { return $this->_insertHyperlinks; } - + /** * Set InsertHyperlinks * @@ -403,7 +391,7 @@ class PHPExcel_Worksheet_Protection function getDeleteColumns() { return $this->_deleteColumns; } - + /** * Set DeleteColumns * @@ -423,7 +411,7 @@ class PHPExcel_Worksheet_Protection function getDeleteRows() { return $this->_deleteRows; } - + /** * Set DeleteRows * @@ -443,7 +431,7 @@ class PHPExcel_Worksheet_Protection function getSelectLockedCells() { return $this->_selectLockedCells; } - + /** * Set SelectLockedCells * @@ -463,7 +451,7 @@ class PHPExcel_Worksheet_Protection function getSort() { return $this->_sort; } - + /** * Set Sort * @@ -483,7 +471,7 @@ class PHPExcel_Worksheet_Protection function getAutoFilter() { return $this->_autoFilter; } - + /** * Set AutoFilter * @@ -503,7 +491,7 @@ class PHPExcel_Worksheet_Protection function getPivotTables() { return $this->_pivotTables; } - + /** * Set PivotTables * @@ -523,7 +511,7 @@ class PHPExcel_Worksheet_Protection function getSelectUnlockedCells() { return $this->_selectUnlockedCells; } - + /** * Set SelectUnlockedCells * @@ -534,7 +522,7 @@ class PHPExcel_Worksheet_Protection $this->_selectUnlockedCells = $pValue; return $this; } - + /** * Get Password (hashed) * diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Row.php b/libraries/PHPExcel/PHPExcel/Worksheet/Row.php index d2105cb10..aa3d1f508 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Row.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Row.php @@ -22,31 +22,13 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Worksheet_CellIterator */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/CellIterator.php'; - - /** * PHPExcel_Worksheet_Row - * + * * Represents a row in PHPExcel_Worksheet, used by PHPExcel_Worksheet_RowIterator * * @category PHPExcel @@ -61,14 +43,14 @@ class PHPExcel_Worksheet_Row * @var PHPExcel_Worksheet */ private $_parent; - + /** * Row index * * @var int */ private $_rowIndex = 0; - + /** * Create a new row * @@ -80,14 +62,14 @@ class PHPExcel_Worksheet_Row $this->_parent = $parent; $this->_rowIndex = $rowIndex; } - + /** * Destructor */ public function __destruct() { unset($this->_parent); } - + /** * Get row index * @@ -96,7 +78,7 @@ class PHPExcel_Worksheet_Row public function getRowIndex() { return $this->_rowIndex; } - + /** * Get cell iterator * diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php b/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php index e956c2424..66497a530 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php @@ -22,7 +22,7 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php b/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php index 58b0dcaf4..e2852f45d 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php @@ -22,38 +22,20 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Worksheet_Row */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Row.php'; - - /** * PHPExcel_Worksheet_RowIterator - * + * * Used to iterate rows in a PHPExcel_Worksheet * * @category PHPExcel * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Worksheet_RowIterator extends IteratorIterator +class PHPExcel_Worksheet_RowIterator extends CachingIterator { /** * PHPExcel_Worksheet to iterate @@ -61,13 +43,13 @@ class PHPExcel_Worksheet_RowIterator extends IteratorIterator * @var PHPExcel_Worksheet */ private $_subject; - + /** * Current iterator position * * @var int */ - private $_position = 0; + private $_position = 1; /** * Create a new row iterator @@ -78,14 +60,14 @@ class PHPExcel_Worksheet_RowIterator extends IteratorIterator // Set subject $this->_subject = $subject; } - + /** * Destructor */ public function __destruct() { unset($this->_subject); } - + /** * Rewind iterator */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php b/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php index 684ef8a21..ab65e612d 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php @@ -22,7 +22,7 @@ * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ @@ -82,10 +82,12 @@ class PHPExcel_Worksheet_SheetView * @return PHPExcel_Worksheet_SheetView */ public function setZoomScale($pValue = 100) { - if (($pValue >= 10 && $pValue <= 400) || is_null($pValue)) { + // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, + // but it is apparently still able to handle any scale >= 1 + if (($pValue >= 1) || is_null($pValue)) { $this->_zoomScale = $pValue; } else { - throw new Exception("Valid scale is between 10 and 400."); + throw new Exception("Scale must be greater than or equal to 1."); } return $this; } @@ -109,10 +111,10 @@ class PHPExcel_Worksheet_SheetView * @return PHPExcel_Worksheet_SheetView */ public function setZoomScaleNormal($pValue = 100) { - if (($pValue >= 10 && $pValue <= 400) || is_null($pValue)) { + if (($pValue >= 1) || is_null($pValue)) { $this->_zoomScaleNormal = $pValue; } else { - throw new Exception("Valid scale is between 10 and 400."); + throw new Exception("Scale must be greater than or equal to 1."); } return $this; } diff --git a/libraries/PHPExcel/PHPExcel/WorksheetIterator.php b/libraries/PHPExcel/PHPExcel/WorksheetIterator.php index 57f0d5c45..da5119f83 100644 --- a/libraries/PHPExcel/PHPExcel/WorksheetIterator.php +++ b/libraries/PHPExcel/PHPExcel/WorksheetIterator.php @@ -22,35 +22,20 @@ * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - - /** * PHPExcel_WorksheetIterator - * + * * Used to iterate worksheets in PHPExcel * * @category PHPExcel * @package PHPExcel * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_WorksheetIterator extends IteratorIterator +class PHPExcel_WorksheetIterator extends CachingIterator { /** * Spreadsheet to iterate @@ -58,7 +43,7 @@ class PHPExcel_WorksheetIterator extends IteratorIterator * @var PHPExcel */ private $_subject; - + /** * Current iterator position * @@ -75,14 +60,14 @@ class PHPExcel_WorksheetIterator extends IteratorIterator // Set subject $this->_subject = $subject; } - + /** * Destructor */ public function __destruct() { unset($this->_subject); } - + /** * Rewind iterator */ diff --git a/libraries/PHPExcel/PHPExcel/Writer/CSV.php b/libraries/PHPExcel/PHPExcel/Writer/CSV.php index fd29f1559..3c722eccf 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/CSV.php +++ b/libraries/PHPExcel/PHPExcel/Writer/CSV.php @@ -22,31 +22,10 @@ * @package PHPExcel_Writer * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_RichText */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - - /** * PHPExcel_Writer_CSV * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php index 81b00922a..62c2606b4 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php @@ -22,73 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_HashTable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; - -/** PHPExcel_IComparable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_IWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Writer_Excel2007_StringTable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/StringTable.php'; - -/** PHPExcel_Writer_Excel2007_ContentTypes */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/ContentTypes.php'; - -/** PHPExcel_Writer_Excel2007_DocProps */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/DocProps.php'; - -/** PHPExcel_Writer_Excel2007_Rels */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Rels.php'; - -/** PHPExcel_Writer_Excel2007_Theme */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Theme.php'; - -/** PHPExcel_Writer_Excel2007_Style */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Style.php'; - -/** PHPExcel_Writer_Excel2007_Workbook */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Workbook.php'; - -/** PHPExcel_Writer_Excel2007_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Worksheet.php'; - -/** PHPExcel_Writer_Excel2007_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Drawing.php'; - -/** PHPExcel_Writer_Excel2007_Comments */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Comments.php'; - - /** * PHPExcel_Writer_Excel2007 * @@ -181,7 +118,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter * @var boolean */ private $_useDiskCaching = false; - + /** * Disk caching directory * @@ -198,7 +135,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter { // Assign PHPExcel $this->setPHPExcel($pPHPExcel); - + // Set up disk caching location $this->_diskCachingDirectory = './'; @@ -558,7 +495,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter */ public function setUseDiskCaching($pValue = false, $pDirectory = null) { $this->_useDiskCaching = $pValue; - + if (!is_null($pDirectory)) { if (is_dir($pDirectory)) { $this->_diskCachingDirectory = $pDirectory; @@ -568,7 +505,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } return $this; } - + /** * Get disk caching directory * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php index 7b559f569..172dde50b 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,46 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Comment */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Comment.php'; - -/** PHPExcel_RichText */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_Comments * @@ -87,13 +51,13 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write } else { $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); } - + // XML header $objWriter->startDocument('1.0','UTF-8','yes'); - + // Comments cache $comments = $pWorksheet->getComments(); - + // Authors cache $authors = array(); $authorId = 0; @@ -102,31 +66,31 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $authors[$comment->getAuthor()] = $authorId++; } } - + // comments $objWriter->startElement('comments'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - + // Loop through authors $objWriter->startElement('authors'); foreach ($authors as $author => $index) { $objWriter->writeElement('author', $author); } $objWriter->endElement(); - + // Loop through comments $objWriter->startElement('commentList'); foreach ($comments as $key => $value) { $this->_writeComment($objWriter, $key, $value, $authors); } $objWriter->endElement(); - + $objWriter->endElement(); // Return return $objWriter->getData(); } - + /** * Write comment to XML format * @@ -142,15 +106,15 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $objWriter->startElement('comment'); $objWriter->writeAttribute('ref', $pCellReference); $objWriter->writeAttribute('authorId', $pAuthors[$pComment->getAuthor()]); - + // text $objWriter->startElement('text'); $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $pComment->getText()); $objWriter->endElement(); - + $objWriter->endElement(); } - + /** * Write VML comments to XML format * @@ -167,13 +131,13 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write } else { $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); } - + // XML header $objWriter->startDocument('1.0','UTF-8','yes'); - + // Comments cache $comments = $pWorksheet->getComments(); - + // xml $objWriter->startElement('xml'); $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); @@ -183,46 +147,46 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write // o:shapelayout $objWriter->startElement('o:shapelayout'); $objWriter->writeAttribute('v:ext', 'edit'); - + // o:idmap $objWriter->startElement('o:idmap'); $objWriter->writeAttribute('v:ext', 'edit'); $objWriter->writeAttribute('data', '1'); $objWriter->endElement(); - + $objWriter->endElement(); - + // v:shapetype $objWriter->startElement('v:shapetype'); $objWriter->writeAttribute('id', '_x0000_t202'); $objWriter->writeAttribute('coordsize', '21600,21600'); $objWriter->writeAttribute('o:spt', '202'); $objWriter->writeAttribute('path', 'm,l,21600r21600,l21600,xe'); - + // v:stroke $objWriter->startElement('v:stroke'); $objWriter->writeAttribute('joinstyle', 'miter'); $objWriter->endElement(); - + // v:path $objWriter->startElement('v:path'); $objWriter->writeAttribute('gradientshapeok', 't'); $objWriter->writeAttribute('o:connecttype', 'rect'); $objWriter->endElement(); - + $objWriter->endElement(); - + // Loop through comments foreach ($comments as $key => $value) { $this->_writeVMLComment($objWriter, $key, $value); } - + $objWriter->endElement(); // Return return $objWriter->getData(); } - + /** * Write VML comment to XML format * @@ -238,7 +202,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $column = PHPExcel_Cell::columnIndexFromString($column); $id = 1024 + $column + $row; $id = substr($id, 0, 4); - + // v:shape $objWriter->startElement('v:shape'); $objWriter->writeAttribute('id', '_x0000_s' . $id); @@ -246,59 +210,59 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $pComment->getMarginLeft() . ';margin-top:' . $pComment->getMarginTop() . ';width:' . $pComment->getWidth() . ';height:' . $pComment->getHeight() . ';z-index:1;visibility:' . ($pComment->getVisible() ? 'visible' : 'hidden')); $objWriter->writeAttribute('fillcolor', '#' . $pComment->getFillColor()->getRGB()); $objWriter->writeAttribute('o:insetmode', 'auto'); - + // v:fill $objWriter->startElement('v:fill'); $objWriter->writeAttribute('color2', '#' . $pComment->getFillColor()->getRGB()); $objWriter->endElement(); - + // v:shadow $objWriter->startElement('v:shadow'); $objWriter->writeAttribute('on', 't'); $objWriter->writeAttribute('color', 'black'); $objWriter->writeAttribute('obscured', 't'); $objWriter->endElement(); - + // v:path $objWriter->startElement('v:path'); $objWriter->writeAttribute('o:connecttype', 'none'); $objWriter->endElement(); - + // v:textbox $objWriter->startElement('v:textbox'); $objWriter->writeAttribute('style', 'mso-direction-alt:auto'); - + // div $objWriter->startElement('div'); $objWriter->writeAttribute('style', 'text-align:left'); $objWriter->endElement(); - + $objWriter->endElement(); - + // x:ClientData $objWriter->startElement('x:ClientData'); $objWriter->writeAttribute('ObjectType', 'Note'); - + // x:MoveWithCells $objWriter->writeElement('x:MoveWithCells', ''); - + // x:SizeWithCells $objWriter->writeElement('x:SizeWithCells', ''); - + // x:Anchor //$objWriter->writeElement('x:Anchor', $column . ', 15, ' . ($row - 2) . ', 10, ' . ($column + 4) . ', 15, ' . ($row + 5) . ', 18'); // x:AutoFill $objWriter->writeElement('x:AutoFill', 'False'); - + // x:Row $objWriter->writeElement('x:Row', ($row - 1)); - + // x:Column $objWriter->writeElement('x:Column', ($column - 1)); - - $objWriter->endElement(); - + + $objWriter->endElement(); + $objWriter->endElement(); } } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php index 17505f5e0..397330c09 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -22,34 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Shared_File */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_ContentTypes * @@ -159,7 +135,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W for ($i = 0; $i < $mediaCount; ++$i) { $extension = ''; $mimeType = ''; - + if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension()); $mimeType = $this->_getImageMimeType( $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath() ); @@ -167,10 +143,10 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType()); $extension = explode('/', $extension); $extension = $extension[1]; - + $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType(); } - + if (!isset( $aMediaContentTypes[$extension]) ) { $aMediaContentTypes[$extension] = $mimeType; @@ -179,7 +155,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W ); } } - + $sheetCount = $pPHPExcel->getSheetCount(); for ($i = 0; $i < $sheetCount; ++$i) { if (count($pPHPExcel->getSheet()->getHeaderFooter()->getImages()) > 0) { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php index 3046cb5ce..4203147ab 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php @@ -22,31 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_DocProps * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php index 584c65d89..c8bc67c0a 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php @@ -22,49 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Worksheet_BaseDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/BaseDrawing.php'; - -/** PHPExcel_Worksheet_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; - -/** PHPExcel_Worksheet_MemoryDrawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Shared_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_Drawing * @@ -204,23 +165,23 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer $objWriter->endElement(); - // a:solidFill - $objWriter->startElement('a:solidFill'); +// // a:solidFill +// $objWriter->startElement('a:solidFill'); - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', 'FFFFFF'); +// // a:srgbClr +// $objWriter->startElement('a:srgbClr'); +// $objWriter->writeAttribute('val', 'FFFFFF'); -/* SHADE - // a:shade - $objWriter->startElement('a:shade'); - $objWriter->writeAttribute('val', '85000'); - $objWriter->endElement(); -*/ +///* SHADE +// // a:shade +// $objWriter->startElement('a:shade'); +// $objWriter->writeAttribute('val', '85000'); +// $objWriter->endElement(); +//*/ - $objWriter->endElement(); +// $objWriter->endElement(); - $objWriter->endElement(); +// $objWriter->endElement(); /* // a:ln $objWriter->startElement('a:ln'); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php index ba81c1be5..e80eb0f33 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php @@ -22,34 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_Rels * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php index 1e67d932d..ca233f541 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,34 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - - /** * PHPExcel_Writer_Excel2007_StringTable * @@ -74,18 +50,19 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr $aStringTable = array(); $cellCollection = null; $aFlippedStringTable = null; // For faster lookup - + // Is an existing table given? if (!is_null($pExistingTable) && is_array($pExistingTable)) { $aStringTable = $pExistingTable; } - + // Fill index array $aFlippedStringTable = $this->flipStringTable($aStringTable); - + // Loop through cells $cellCollection = $pSheet->getCellCollection(); - foreach ($cellCollection as $cell) { + foreach ($cellCollection as $cellID) { + $cell = $pSheet->getCell($cellID); if (!is_object($cell->getValue()) && !isset($aFlippedStringTable[$cell->getValue()]) && !is_null($cell->getValue()) && @@ -94,7 +71,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr ) { $aStringTable[] = $cell->getValue(); $aFlippedStringTable[$cell->getValue()] = 1; - + } else if ($cell->getValue() instanceof PHPExcel_RichText && !isset($aFlippedStringTable[$cell->getValue()->getHashCode()]) && !is_null($cell->getValue()) @@ -110,7 +87,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr throw new Exception("Invalid PHPExcel_Worksheet object passed."); } } - + /** * Write string table to XML format * @@ -120,7 +97,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr */ public function writeStringTable($pStringTable = null) { - if (!is_null($pStringTable)) { + if (!is_null($pStringTable)) { // Create XML writer $objWriter = null; if ($this->getParentWriter()->getUseDiskCaching()) { @@ -128,19 +105,19 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr } else { $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); } - + // XML header $objWriter->startDocument('1.0','UTF-8','yes'); - + // String table $objWriter->startElement('sst'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); $objWriter->writeAttribute('uniqueCount', count($pStringTable)); - + // Loop through string table foreach ($pStringTable as $textElement) { $objWriter->startElement('si'); - + if (! $textElement instanceof PHPExcel_RichText) { $textToWrite = PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $textElement ); $objWriter->startElement('t'); @@ -152,10 +129,10 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr } else if ($textElement instanceof PHPExcel_RichText) { $this->writeRichText($objWriter, $textElement); } - + $objWriter->endElement(); } - + $objWriter->endElement(); // Return @@ -179,7 +156,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr foreach ($elements as $element) { // r $objWriter->startElement('r'); - + // rPr if ($element instanceof PHPExcel_RichText_Run) { // rPr @@ -189,17 +166,17 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr $objWriter->startElement('rFont'); $objWriter->writeAttribute('val', $element->getFont()->getName()); $objWriter->endElement(); - + // Bold $objWriter->startElement('b'); $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false')); $objWriter->endElement(); - + // Italic $objWriter->startElement('i'); $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false')); $objWriter->endElement(); - + // Superscript / subscript if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { $objWriter->startElement('vertAlign'); @@ -210,40 +187,40 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr } $objWriter->endElement(); } - + // Strikethrough $objWriter->startElement('strike'); $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false')); - $objWriter->endElement(); - + $objWriter->endElement(); + // Color $objWriter->startElement('color'); $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB()); - $objWriter->endElement(); - + $objWriter->endElement(); + // Size $objWriter->startElement('sz'); $objWriter->writeAttribute('val', $element->getFont()->getSize()); $objWriter->endElement(); - + // Underline $objWriter->startElement('u'); $objWriter->writeAttribute('val', $element->getFont()->getUnderline()); $objWriter->endElement(); - + $objWriter->endElement(); } - + // t $objWriter->startElement('t'); $objWriter->writeAttribute('xml:space', 'preserve'); $objWriter->writeRaw(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); $objWriter->endElement(); - + $objWriter->endElement(); - } + } } - + /** * Flip string table (for index searching) * @@ -253,7 +230,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr public function flipStringTable($stringTable = array()) { // Return value $returnValue = array(); - + // Loop through stringtable and add flipped items to $returnValue foreach ($stringTable as $key => $value) { if (! $value instanceof PHPExcel_RichText) { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php index 8a41a6f35..8cfa52d49 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php @@ -22,58 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Style */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; - -/** PHPExcel_Style_Borders */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php'; - -/** PHPExcel_Style_Border */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Border.php'; - -/** PHPExcel_Style_Color */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; - -/** PHPExcel_Style_Fill */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Fill.php'; - -/** PHPExcel_Style_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; - -/** PHPExcel_Style_NumberFormat */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; - -/** PHPExcel_Style_Conditional */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Conditional.php'; - -/** PHPExcel_Style_Protection */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_Style * @@ -330,19 +282,17 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->writeAttribute('val', $pFont->getSize()); $objWriter->endElement(); - // Bold - if ($pFont->getBold()) { - $objWriter->startElement('b'); - $objWriter->writeAttribute('val', 'true'); - $objWriter->endElement(); - } + // Bold. We explicitly write this element also when false (like MS Office Excel 2007 does + // for conditional formatting). Otherwise it will apparently not be picked up in conditional + // formatting style dialog + $objWriter->startElement('b'); + $objWriter->writeAttribute('val', $pFont->getBold() ? '1' : '0'); + $objWriter->endElement(); // Italic - if ($pFont->getItalic()) { - $objWriter->startElement('i'); - $objWriter->writeAttribute('val', 'true'); - $objWriter->endElement(); - } + $objWriter->startElement('i'); + $objWriter->writeAttribute('val', $pFont->getItalic() ? '1' : '0'); + $objWriter->endElement(); // Superscript / subscript if ($pFont->getSuperScript() || $pFont->getSubScript()) { @@ -361,11 +311,9 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->endElement(); // Strikethrough - if ($pFont->getStrikethrough()) { - $objWriter->startElement('strike'); - $objWriter->writeAttribute('val', 'true'); - $objWriter->endElement(); - } + $objWriter->startElement('strike'); + $objWriter->writeAttribute('val', $pFont->getStrikethrough() ? '1' : '0'); + $objWriter->endElement(); // Foreground color $objWriter->startElement('color'); @@ -425,13 +373,13 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('xf'); $objWriter->writeAttribute('xfId', 0); $objWriter->writeAttribute('fontId', (int)$this->getParentWriter()->getFontHashTable()->getIndexForHashCode($pStyle->getFont()->getHashCode())); - + if ($pStyle->getNumberFormat()->getBuiltInFormatCode() === false) { $objWriter->writeAttribute('numFmtId', (int)($this->getParentWriter()->getNumFmtHashTable()->getIndexForHashCode($pStyle->getNumberFormat()->getHashCode()) + 164) ); } else { $objWriter->writeAttribute('numFmtId', (int)$pStyle->getNumberFormat()->getBuiltInFormatCode()); } - + $objWriter->writeAttribute('fillId', (int)$this->getParentWriter()->getFillHashTable()->getIndexForHashCode($pStyle->getFill()->getHashCode())); $objWriter->writeAttribute('borderId', (int)$this->getParentWriter()->getBordersHashTable()->getIndexForHashCode($pStyle->getBorders()->getHashCode())); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php index cf4565c78..f62fdbb42 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,31 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_DocProps * @@ -64,7 +43,7 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa * @throws Exception */ public function writeTheme(PHPExcel $pPHPExcel = null) - { + { // Create XML writer $objWriter = null; if ($this->getParentWriter()->getUseDiskCaching()) { @@ -72,7 +51,7 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa } else { $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); } - + // XML header $objWriter->startDocument('1.0','UTF-8','yes'); @@ -80,533 +59,533 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('a:theme'); $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); $objWriter->writeAttribute('name', 'Office Theme'); - + // a:themeElements $objWriter->startElement('a:themeElements'); - + { // a:clrScheme $objWriter->startElement('a:clrScheme'); $objWriter->writeAttribute('name', 'Office'); - + // a:dk1 $objWriter->startElement('a:dk1'); - + // a:sysClr $objWriter->startElement('a:sysClr'); $objWriter->writeAttribute('val', 'windowText'); $objWriter->writeAttribute('lastClr', '000000'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:lt1 $objWriter->startElement('a:lt1'); - + // a:sysClr $objWriter->startElement('a:sysClr'); $objWriter->writeAttribute('val', 'window'); $objWriter->writeAttribute('lastClr', 'FFFFFF'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:dk2 $objWriter->startElement('a:dk2'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '1F497D'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:lt2 $objWriter->startElement('a:lt2'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', 'EEECE1'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:accent1 $objWriter->startElement('a:accent1'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '4F81BD'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:accent2 $objWriter->startElement('a:accent2'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', 'C0504D'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:accent3 $objWriter->startElement('a:accent3'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '9BBB59'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:accent4 $objWriter->startElement('a:accent4'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '8064A2'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:accent5 $objWriter->startElement('a:accent5'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '4BACC6'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:accent6 $objWriter->startElement('a:accent6'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', 'F79646'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:hlink $objWriter->startElement('a:hlink'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '0000FF'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:folHlink $objWriter->startElement('a:folHlink'); - + // a:sysClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '800080'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); } - + { // a:fontScheme $objWriter->startElement('a:fontScheme'); $objWriter->writeAttribute('name', 'Office'); - + // a:majorFont $objWriter->startElement('a:majorFont'); - + // a:latin $objWriter->startElement('a:latin'); $objWriter->writeAttribute('typeface', 'Cambria'); $objWriter->endElement(); - - // a:ea + + // a:ea $objWriter->startElement('a:ea'); $objWriter->writeAttribute('typeface', ''); $objWriter->endElement(); - + // a:cs $objWriter->startElement('a:cs'); $objWriter->writeAttribute('typeface', ''); - $objWriter->endElement(); - + $objWriter->endElement(); + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Jpan'); $objWriter->writeAttribute('typeface', '?? ?????'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hang'); $objWriter->writeAttribute('typeface', '?? ??'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hans'); $objWriter->writeAttribute('typeface', '??'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hant'); $objWriter->writeAttribute('typeface', '????'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Arab'); $objWriter->writeAttribute('typeface', 'Times New Roman'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hebr'); $objWriter->writeAttribute('typeface', 'Times New Roman'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Thai'); $objWriter->writeAttribute('typeface', 'Tahoma'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Ethi'); $objWriter->writeAttribute('typeface', 'Nyala'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Beng'); $objWriter->writeAttribute('typeface', 'Vrinda'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Gujr'); $objWriter->writeAttribute('typeface', 'Shruti'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Khmr'); $objWriter->writeAttribute('typeface', 'MoolBoran'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Knda'); $objWriter->writeAttribute('typeface', 'Tunga'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Guru'); $objWriter->writeAttribute('typeface', 'Raavi'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Cans'); $objWriter->writeAttribute('typeface', 'Euphemia'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Cher'); $objWriter->writeAttribute('typeface', 'Plantagenet Cherokee'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Yiii'); $objWriter->writeAttribute('typeface', 'Microsoft Yi Baiti'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Tibt'); $objWriter->writeAttribute('typeface', 'Microsoft Himalaya'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Thaa'); $objWriter->writeAttribute('typeface', 'MV Boli'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Deva'); $objWriter->writeAttribute('typeface', 'Mangal'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Telu'); $objWriter->writeAttribute('typeface', 'Gautami'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Taml'); $objWriter->writeAttribute('typeface', 'Latha'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Syrc'); $objWriter->writeAttribute('typeface', 'Estrangelo Edessa'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Orya'); $objWriter->writeAttribute('typeface', 'Kalinga'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Mlym'); $objWriter->writeAttribute('typeface', 'Kartika'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Laoo'); $objWriter->writeAttribute('typeface', 'DokChampa'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Sinh'); $objWriter->writeAttribute('typeface', 'Iskoola Pota'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Mong'); $objWriter->writeAttribute('typeface', 'Mongolian Baiti'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Viet'); $objWriter->writeAttribute('typeface', 'Times New Roman'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Uigh'); $objWriter->writeAttribute('typeface', 'Microsoft Uighur'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:minorFont $objWriter->startElement('a:minorFont'); - + // a:latin $objWriter->startElement('a:latin'); $objWriter->writeAttribute('typeface', 'Calibri'); $objWriter->endElement(); - - // a:ea + + // a:ea $objWriter->startElement('a:ea'); $objWriter->writeAttribute('typeface', ''); $objWriter->endElement(); - + // a:cs $objWriter->startElement('a:cs'); $objWriter->writeAttribute('typeface', ''); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Jpan'); $objWriter->writeAttribute('typeface', '?? ?????'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hang'); $objWriter->writeAttribute('typeface', '?? ??'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hans'); $objWriter->writeAttribute('typeface', '??'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hant'); $objWriter->writeAttribute('typeface', '????'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Arab'); $objWriter->writeAttribute('typeface', 'Arial'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Hebr'); $objWriter->writeAttribute('typeface', 'Arial'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Thai'); $objWriter->writeAttribute('typeface', 'Tahoma'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Ethi'); $objWriter->writeAttribute('typeface', 'Nyala'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Beng'); $objWriter->writeAttribute('typeface', 'Vrinda'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Gujr'); $objWriter->writeAttribute('typeface', 'Shruti'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Khmr'); $objWriter->writeAttribute('typeface', 'DaunPenh'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Knda'); $objWriter->writeAttribute('typeface', 'Tunga'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Guru'); $objWriter->writeAttribute('typeface', 'Raavi'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Cans'); $objWriter->writeAttribute('typeface', 'Euphemia'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Cher'); $objWriter->writeAttribute('typeface', 'Plantagenet Cherokee'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Yiii'); $objWriter->writeAttribute('typeface', 'Microsoft Yi Baiti'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Tibt'); $objWriter->writeAttribute('typeface', 'Microsoft Himalaya'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Thaa'); $objWriter->writeAttribute('typeface', 'MV Boli'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Deva'); $objWriter->writeAttribute('typeface', 'Mangal'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Telu'); $objWriter->writeAttribute('typeface', 'Gautami'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Taml'); $objWriter->writeAttribute('typeface', 'Latha'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Syrc'); $objWriter->writeAttribute('typeface', 'Estrangelo Edessa'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Orya'); $objWriter->writeAttribute('typeface', 'Kalinga'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Mlym'); $objWriter->writeAttribute('typeface', 'Kartika'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Laoo'); $objWriter->writeAttribute('typeface', 'DokChampa'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Sinh'); $objWriter->writeAttribute('typeface', 'Iskoola Pota'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Mong'); $objWriter->writeAttribute('typeface', 'Mongolian Baiti'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Viet'); $objWriter->writeAttribute('typeface', 'Arial'); $objWriter->endElement(); - + // a:font $objWriter->startElement('a:font'); $objWriter->writeAttribute('script', 'Uigh'); $objWriter->writeAttribute('typeface', 'Microsoft Uighur'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); } @@ -614,107 +593,107 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa // a:fmtScheme $objWriter->startElement('a:fmtScheme'); $objWriter->writeAttribute('name', 'Office'); - + // a:fillStyleLst $objWriter->startElement('a:fillStyleLst'); - + // a:solidFill $objWriter->startElement('a:solidFill'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gradFill $objWriter->startElement('a:gradFill'); $objWriter->writeAttribute('rotWithShape', '1'); - + // a:gsLst $objWriter->startElement('a:gsLst'); // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '0'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:tint $objWriter->startElement('a:tint'); $objWriter->writeAttribute('val', '50000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '300000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '35000'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:tint $objWriter->startElement('a:tint'); $objWriter->writeAttribute('val', '37000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '300000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '100000'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:tint $objWriter->startElement('a:tint'); $objWriter->writeAttribute('val', '15000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '350000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:lin $objWriter->startElement('a:lin'); $objWriter->writeAttribute('ang', '16200000'); $objWriter->writeAttribute('scaled', '1'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gradFill $objWriter->startElement('a:gradFill'); $objWriter->writeAttribute('rotWithShape', '1'); - + // a:gsLst $objWriter->startElement('a:gsLst'); @@ -725,21 +704,21 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '51000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '130000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '80000'); @@ -747,21 +726,21 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '93000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '130000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '100000'); @@ -769,31 +748,31 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '94000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '135000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:lin $objWriter->startElement('a:lin'); $objWriter->writeAttribute('ang', '16200000'); $objWriter->writeAttribute('scaled', '0'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); // a:lnStyleLst @@ -805,42 +784,42 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->writeAttribute('cap', 'flat'); $objWriter->writeAttribute('cmpd', 'sng'); $objWriter->writeAttribute('algn', 'ctr'); - + // a:solidFill $objWriter->startElement('a:solidFill'); // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '95000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '105000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:prstDash $objWriter->startElement('a:prstDash'); $objWriter->writeAttribute('val', 'solid'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:ln $objWriter->startElement('a:ln'); $objWriter->writeAttribute('w', '25400'); $objWriter->writeAttribute('cap', 'flat'); $objWriter->writeAttribute('cmpd', 'sng'); $objWriter->writeAttribute('algn', 'ctr'); - + // a:solidFill $objWriter->startElement('a:solidFill'); @@ -848,23 +827,23 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:prstDash $objWriter->startElement('a:prstDash'); $objWriter->writeAttribute('val', 'solid'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:ln $objWriter->startElement('a:ln'); $objWriter->writeAttribute('w', '38100'); $objWriter->writeAttribute('cap', 'flat'); $objWriter->writeAttribute('cmpd', 'sng'); $objWriter->writeAttribute('algn', 'ctr'); - + // a:solidFill $objWriter->startElement('a:solidFill'); @@ -872,16 +851,16 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); $objWriter->endElement(); - + $objWriter->endElement(); - + // a:prstDash $objWriter->startElement('a:prstDash'); $objWriter->writeAttribute('val', 'solid'); $objWriter->endElement(); - - $objWriter->endElement(); - + + $objWriter->endElement(); + $objWriter->endElement(); @@ -891,167 +870,167 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa // a:effectStyle $objWriter->startElement('a:effectStyle'); - + // a:effectLst $objWriter->startElement('a:effectLst'); // a:outerShdw $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', '40000'); - $objWriter->writeAttribute('dist', '20000'); - $objWriter->writeAttribute('dir', '5400000'); - $objWriter->writeAttribute('rotWithShape', '0'); - - // a:srgbClr - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', '000000'); - - // a:alpha - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', '38000'); - $objWriter->endElement(); - - $objWriter->endElement(); - - $objWriter->endElement(); - - $objWriter->endElement(); - - $objWriter->endElement(); - - // a:effectStyle - $objWriter->startElement('a:effectStyle'); - - // a:effectLst - $objWriter->startElement('a:effectLst'); - - // a:outerShdw - $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', '40000'); - $objWriter->writeAttribute('dist', '23000'); - $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '20000'); + $objWriter->writeAttribute('dir', '5400000'); $objWriter->writeAttribute('rotWithShape', '0'); - + // a:srgbClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '000000'); - + // a:alpha $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', '35000'); - $objWriter->endElement(); - - $objWriter->endElement(); - + $objWriter->writeAttribute('val', '38000'); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); // a:effectStyle $objWriter->startElement('a:effectStyle'); - + // a:effectLst $objWriter->startElement('a:effectLst'); // a:outerShdw $objWriter->startElement('a:outerShdw'); - $objWriter->writeAttribute('blurRad', '40000'); - $objWriter->writeAttribute('dist', '23000'); - $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '23000'); + $objWriter->writeAttribute('dir', '5400000'); $objWriter->writeAttribute('rotWithShape', '0'); - + // a:srgbClr $objWriter->startElement('a:srgbClr'); $objWriter->writeAttribute('val', '000000'); - + // a:alpha $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', '35000'); - $objWriter->endElement(); - - $objWriter->endElement(); - + $objWriter->writeAttribute('val', '35000'); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); - + $objWriter->endElement(); - + + $objWriter->endElement(); + + // a:effectStyle + $objWriter->startElement('a:effectStyle'); + + // a:effectLst + $objWriter->startElement('a:effectLst'); + + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '23000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); + + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '35000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + // a:scene3d $objWriter->startElement('a:scene3d'); // a:camera $objWriter->startElement('a:camera'); - $objWriter->writeAttribute('prst', 'orthographicFront'); + $objWriter->writeAttribute('prst', 'orthographicFront'); // a:rot $objWriter->startElement('a:rot'); $objWriter->writeAttribute('lat', '0'); $objWriter->writeAttribute('lon', '0'); $objWriter->writeAttribute('rev', '0'); - $objWriter->endElement(); - + $objWriter->endElement(); + $objWriter->endElement(); // a:lightRig $objWriter->startElement('a:lightRig'); - $objWriter->writeAttribute('rig', 'threePt'); - $objWriter->writeAttribute('dir', 't'); + $objWriter->writeAttribute('rig', 'threePt'); + $objWriter->writeAttribute('dir', 't'); // a:rot $objWriter->startElement('a:rot'); $objWriter->writeAttribute('lat', '0'); $objWriter->writeAttribute('lon', '0'); $objWriter->writeAttribute('rev', '1200000'); - $objWriter->endElement(); - + $objWriter->endElement(); + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:sp3d $objWriter->startElement('a:sp3d'); // a:bevelT $objWriter->startElement('a:bevelT'); - $objWriter->writeAttribute('w', '63500'); - $objWriter->writeAttribute('h', '25400'); + $objWriter->writeAttribute('w', '63500'); + $objWriter->writeAttribute('h', '25400'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); $objWriter->endElement(); // a:bgFillStyleLst $objWriter->startElement('a:bgFillStyleLst'); - + // a:solidFill $objWriter->startElement('a:solidFill'); // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - $objWriter->endElement(); - + $objWriter->endElement(); + $objWriter->endElement(); - + // a:gradFill $objWriter->startElement('a:gradFill'); $objWriter->writeAttribute('rotWithShape', '1'); - + // a:gsLst $objWriter->startElement('a:gsLst'); // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '0'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:tint $objWriter->startElement('a:tint'); $objWriter->writeAttribute('val', '40000'); @@ -1061,15 +1040,15 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '350000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '40000'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); @@ -1078,45 +1057,45 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('a:tint'); $objWriter->writeAttribute('val', '45000'); $objWriter->endElement(); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '99000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '350000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '100000'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '20000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '255000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:path $objWriter->startElement('a:path'); $objWriter->writeAttribute('path', 'circle'); @@ -1128,26 +1107,26 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->writeAttribute('r', '50000'); $objWriter->writeAttribute('b', '180000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gradFill $objWriter->startElement('a:gradFill'); $objWriter->writeAttribute('rotWithShape', '1'); - + // a:gsLst $objWriter->startElement('a:gsLst'); // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '0'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:tint $objWriter->startElement('a:tint'); $objWriter->writeAttribute('val', '80000'); @@ -1157,35 +1136,35 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '300000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:gs $objWriter->startElement('a:gs'); $objWriter->writeAttribute('pos', '100000'); - + // a:schemeClr $objWriter->startElement('a:schemeClr'); $objWriter->writeAttribute('val', 'phClr'); - + // a:shade $objWriter->startElement('a:shade'); $objWriter->writeAttribute('val', '30000'); $objWriter->endElement(); - + // a:satMod $objWriter->startElement('a:satMod'); $objWriter->writeAttribute('val', '200000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + // a:path $objWriter->startElement('a:path'); $objWriter->writeAttribute('path', 'circle'); @@ -1197,24 +1176,24 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->writeAttribute('r', '50000'); $objWriter->writeAttribute('b', '50000'); $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); - + $objWriter->endElement(); } - + $objWriter->endElement(); - + // a:objectDefaults $objWriter->writeElement('a:objectDefaults', null); - + // a:extraClrSchemeLst $objWriter->writeElement('a:extraClrSchemeLst', null); - + $objWriter->endElement(); // Return diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php index 727a5d32f..0501fe478 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php @@ -22,37 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel */ -require_once PHPEXCEL_ROOT . 'PHPExcel.php'; - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_Workbook * @@ -142,13 +115,13 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write private function _writeWorkbookPr(PHPExcel_Shared_XMLWriter $objWriter = null) { $objWriter->startElement('workbookPr'); - + if (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) { $objWriter->writeAttribute('date1904', '1'); } - + $objWriter->writeAttribute('codeName', 'ThisWorkbook'); - + $objWriter->endElement(); } @@ -342,7 +315,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write $objWriter->startElement('definedName'); $objWriter->writeAttribute('name', $pNamedRange->getName()); if ($pNamedRange->getLocalOnly()) { - $objWriter->writeAttribute('localSheetId', $pNamedRange->getWorksheet()->getParent()->getIndex($pNamedRange->getWorksheet())); + $objWriter->writeAttribute('localSheetId', $pNamedRange->getScope()->getParent()->getIndex($pNamedRange->getScope())); } // Create absolute coordinate and write as raw text diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php index 30fdc5f87..bcfa3f498 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php @@ -22,52 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Writer_Excel2007 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007.php'; - -/** PHPExcel_Writer_Excel2007_WriterPart */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/WriterPart.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Style_Conditional */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Conditional.php'; - -/** PHPExcel_Style_NumberFormat */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; - -/** PHPExcel_Shared_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_RichText */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; - -/** PHPExcel_Shared_XMLWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; - - /** * PHPExcel_Writer_Excel2007_Worksheet * @@ -196,7 +154,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB()); $objWriter->endElement(); } - + // outlinePr $objWriter->startElement('outlinePr'); $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0')); @@ -244,13 +202,13 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $sheetSelected = false; if ($this->getParentWriter()->getPHPExcel()->getIndex($pSheet) == $this->getParentWriter()->getPHPExcel()->getActiveSheetIndex()) $sheetSelected = true; - - + + // sheetView $objWriter->startElement('sheetView'); $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0'); $objWriter->writeAttribute('workbookViewId', '0'); - + // Zoom scales if ($pSheet->getSheetView()->getZoomScale() != 100) { $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale()); @@ -265,7 +223,14 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ } else { $objWriter->writeAttribute('showGridLines', 'false'); } - + + // Row and column headers + if ($pSheet->getShowRowColHeaders()) { + $objWriter->writeAttribute('showRowColHeaders', '1'); + } else { + $objWriter->writeAttribute('showRowColHeaders', '0'); + } + // Right-to-left if ($pSheet->getRightToLeft()) { $objWriter->writeAttribute('rightToLeft', 'true'); @@ -485,7 +450,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ && $conditional->getOperatorType() != PHPExcel_Style_Conditional::OPERATOR_NONE) { $objWriter->writeAttribute('operator', $conditional->getOperatorType()); } - + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT && !is_null($conditional->getText())) { $objWriter->writeAttribute('text', $conditional->getText()); @@ -890,7 +855,8 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $cellCollection = $pSheet->getCellCollection(); $cellsByRow = array(); - foreach ($cellCollection as $cell) { + foreach ($cellCollection as $cellID) { + $cell = $pSheet->getCell($cellID); $cellsByRow[$cell->getRow()][] = $cell; } @@ -905,40 +871,40 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $rowDimension->getCollapsed() == true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null; - - if ($writeCurrentRow) { + + if ($writeCurrentRow) { // Start a new row $objWriter->startElement('row'); $objWriter->writeAttribute('r', $currentRow); $objWriter->writeAttribute('spans', '1:' . $colCount); - + // Row dimensions if ($rowDimension->getRowHeight() >= 0) { $objWriter->writeAttribute('customHeight', '1'); $objWriter->writeAttribute('ht', PHPExcel_Shared_String::FormatNumber($rowDimension->getRowHeight())); } - + // Row visibility if ($rowDimension->getVisible() == false) { $objWriter->writeAttribute('hidden', 'true'); } - + // Collapsed if ($rowDimension->getCollapsed() == true) { $objWriter->writeAttribute('collapsed', 'true'); } - + // Outline level if ($rowDimension->getOutlineLevel() > 0) { $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel()); } - + // Style if ($rowDimension->getXfIndex() !== null) { $objWriter->writeAttribute('s', $rowDimension->getXfIndex()); $objWriter->writeAttribute('customFormat', '1'); } - + // Write cells if (isset($cellsByRow[$currentRow])) { foreach($cellsByRow[$currentRow] as $cell) { @@ -946,7 +912,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $this->_writeCell($objWriter, $pSheet, $cell, $pStringTable, $aFlippedStringTable); } } - + // End row $objWriter->endElement(); } @@ -970,6 +936,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ */ private function _writeCell(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, PHPExcel_Cell $pCell = null, $pStringTable = null, $pFlippedStringTable = null) { + $pCell->attach($pSheet); if (is_array($pStringTable) && is_array($pFlippedStringTable)) { // Cell $objWriter->startElement('c'); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php index c09d05a19..2b50fefb2 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php @@ -8,12 +8,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -22,22 +22,10 @@ * @package PHPExcel_Writer_Excel2007 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_IWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; - - /** * PHPExcel_Writer_Excel2007_WriterPart * @@ -53,7 +41,7 @@ abstract class PHPExcel_Writer_Excel2007_WriterPart * @var PHPExcel_Writer_IWriter */ private $_parentWriter; - + /** * Set parent IWriter object * @@ -63,7 +51,7 @@ abstract class PHPExcel_Writer_Excel2007_WriterPart public function setParentWriter(PHPExcel_Writer_IWriter $pWriter = null) { $this->_parentWriter = $pWriter; } - + /** * Get parent IWriter object * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5.php index 050e066f8..3694c1a8a 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5.php @@ -22,43 +22,10 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_HashTable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; - -/** PHPExcel_Shared_File */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; - -/** PHPExcel_Shared_OLE_PPS_Root */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_Root.php'; - -/** PHPExcel_Shared_OLE_PPS_File */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_File.php'; - -/** PHPExcel_Writer_Excel5_Parser */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Parser.php'; - -/** PHPExcel_Writer_Excel5_Workbook */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Workbook.php'; - - /** * PHPExcel_Writer_Excel5 * @@ -89,13 +56,6 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter */ private $_BIFF_version; - /** - * Temporary storage directory - * - * @var string - */ - private $_tempDir = ''; - /** * Total number of shared strings in workbook * @@ -141,13 +101,12 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $this->_preCalculateFormulas = true; $this->_phpExcel = $phpExcel; $this->_BIFF_version = 0x0600; - $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); - + $this->_str_total = 0; $this->_str_unique = 0; $this->_str_table = array(); $this->_parser = new PHPExcel_Writer_Excel5_Parser($this->_BIFF_version); - + } /** @@ -158,11 +117,6 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter */ public function save($pFilename = null) { - // check mbstring.func_overload - if (ini_get('mbstring.func_overload') != 0) { - throw new Exception('Multibyte string function overloading in PHP must be disabled.'); - } - // garbage collect $this->_phpExcel->garbageCollect(); @@ -174,17 +128,17 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter // Initialise workbook writer $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, $this->_BIFF_version, - $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser, $this->_tempDir); + $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser); // Initialise worksheet writers $countSheets = count($this->_phpExcel->getAllSheets()); for ($i = 0; $i < $countSheets; ++$i) { $phpSheet = $this->_phpExcel->getSheet($i); - + $writerWorksheet = new PHPExcel_Writer_Excel5_Worksheet($this->_BIFF_version, $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, - $this->_parser, $this->_tempDir, + $this->_parser, $this->_preCalculateFormulas, $phpSheet); $this->_writerWorksheets[$i] = $writerWorksheet; @@ -206,11 +160,6 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $workbookStreamName = ($this->_BIFF_version == 0x0600) ? 'Workbook' : 'Book'; $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName)); - if ($this->_tempDir != '') { - $OLE->setTempDir($this->_tempDir); - } - $res = $OLE->init(); - // Write the worksheet streams before the global workbook stream, // because the byte sizes of these are needed in the global workbook stream $worksheetSizes = array(); @@ -224,49 +173,25 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter // add binary data for sheet streams for ($i = 0; $i < $countSheets; ++$i) { - while ( ($tmp = $this->_writerWorksheets[$i]->getData()) !== false ) { - $OLE->append($tmp); - } + $OLE->append($this->_writerWorksheets[$i]->getData()); } $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), array($OLE)); - if ($this->_tempDir != '') { - $root->setTempDir($this->_tempDir); - } - // save the OLE file $res = $root->save($pFilename); PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); - - // clean up - foreach ($this->_writerWorksheets as $sheet) { - $sheet->cleanup(); - } - } - - /** - * Get temporary storage directory - * - * @return string - */ - public function getTempDir() { - return $this->_tempDir; } /** * Set temporary storage directory * + * @deprecated * @param string $pValue Temporary storage directory * @throws Exception Exception when directory does not exist * @return PHPExcel_Writer_Excel5 */ public function setTempDir($pValue = '') { - if (is_dir($pValue)) { - $this->_tempDir = $pValue; - } else { - throw new Exception("Directory does not exist: $pValue"); - } return $this; } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php index b293ddeeb..a19463f7f 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php @@ -22,7 +22,7 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class): @@ -73,7 +73,7 @@ class PHPExcel_Writer_Excel5_BIFFwriter * The BIFF/Excel version (5). * @var integer */ - var $_BIFF_version = 0x0500; + public $_BIFF_version = 0x0500; /** * The byte order of this architecture. 0 => little endian, 1 => big endian @@ -85,20 +85,20 @@ class PHPExcel_Writer_Excel5_BIFFwriter * The string containing the data of the BIFF stream * @var string */ - var $_data; + public $_data; /** * The size of the data in bytes. Should be the same as strlen($this->_data) * @var integer */ - var $_datasize; + public $_datasize; /** * The maximum length for a BIFF record (excluding record header and length field). See _addContinue() * @var integer * @see _addContinue() */ - var $_limit; + public $_limit; /** * Constructor diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php index 4d5f22bd1..965f2eeb7 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php @@ -22,7 +22,7 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php index 97a553140..d3b1c248e 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php @@ -22,24 +22,9 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ - -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_Style_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; - /** * PHPExcel_Writer_Excel5_Font diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php index 116513d45..867d4c6cb 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php @@ -22,7 +22,7 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Parser (used as the base for this class): @@ -50,21 +50,6 @@ // */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_Writer_Excel5_BIFFwriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/BIFFwriter.php'; - - /** * PHPExcel_Writer_Excel5_Parser * @@ -74,53 +59,67 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/BIFFwriter.php'; */ class PHPExcel_Writer_Excel5_Parser { + /** Constants */ + // Sheet title in unquoted form + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] + // Moreover, there are valid sheet title characters that cannot occur in unquoted form (there may be more?) + // +-% '^&<>=,;#()"{} + const REGEX_SHEET_TITLE_UNQUOTED = '[^\*\:\/\\\\\?\[\]\+\-\% \\\'\^\&\<\>\=\,\;\#\(\)\"\{\}]+'; + + // Sheet title in quoted form (without surrounding quotes) + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] (usual invalid sheet title characters) + // Single quote is represented as a pair '' + const REGEX_SHEET_TITLE_QUOTED = '(([^\*\:\/\\\\\?\[\]\\\'])+|(\\\'\\\')+)+'; + /** * The index of the character we are currently looking at * @var integer */ - var $_current_char; + public $_current_char; /** * The token we are working on. * @var string */ - var $_current_token; + public $_current_token; /** * The formula to parse * @var string */ - var $_formula; + public $_formula; /** * The character ahead of the current char * @var string */ - var $_lookahead; + public $_lookahead; /** * The parse tree to be generated * @var string */ - var $_parse_tree; + public $_parse_tree; /** * Array of external sheets * @var array */ - var $_ext_sheets; + public $_ext_sheets; /** * Array of sheet references in the form of REF structures * @var array */ - var $_references; + public $_references; /** * The BIFF version for the workbook * @var integer */ - var $_BIFF_version; + public $_BIFF_version; /** * The class constructor @@ -534,27 +533,23 @@ class PHPExcel_Writer_Excel5_Parser return $this->_convertRef2d($token); // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 - } elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { return $this->_convertRef3d($token); // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 - } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { return $this->_convertRef3d($token); - // match ranges like A1:B2 - } elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token)) { - return $this->_convertRange2d($token); - - // match ranges like A1..B2 - } elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token)) { + // match ranges like A1:B2 or $A$1:$B$2 + } elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $token)) { return $this->_convertRange2d($token); // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 - } elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { return $this->_convertRange3d($token); // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 - } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { return $this->_convertRange3d($token); // operators (including parentheses) @@ -644,18 +639,15 @@ class PHPExcel_Writer_Excel5_Parser * Convert an Excel range such as A1:D4 to a ptgRefV. * * @access private - * @param string $range An Excel range in the A1:A2 or A1..A2 format. + * @param string $range An Excel range in the A1:A2 */ function _convertRange2d($range, $class=0) { // TODO: possible class value 0,1,2 check Formula.pm // Split the range into 2 cell refs - if (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\:([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) { + if (preg_match('/^(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)\:(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)$/', $range)) { list($cell1, $cell2) = explode(':', $range); - } elseif (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\.\.([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) { - list($cell1, $cell2) = explode('..', $range); - } else { // TODO: use real error codes throw new Exception("Unknown range separator"); @@ -691,7 +683,7 @@ class PHPExcel_Writer_Excel5_Parser */ function _convertRange3d($token) { - $class = 2; // as far as I know, this is magick. + $class = 0; // formulas like Sheet1!$A$1:$A$2 in list type data validation need this class (0x3B) // Split the ref at the ! symbol list($ext_ref, $range) = explode('!', $token); @@ -856,6 +848,7 @@ class PHPExcel_Writer_Excel5_Parser { $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + $ext_ref = str_replace('\'\'', '\'', $ext_ref); // Replace escaped '' with ' // Check if there is a sheet range eg., Sheet1:Sheet2. if (preg_match("/:/", $ext_ref)) { @@ -1156,7 +1149,7 @@ class PHPExcel_Writer_Excel5_Parser return $token; break; default: - // if it's a reference + // if it's a reference A1 or $A$1 or $A1 or A$1 if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.') and @@ -1165,39 +1158,33 @@ class PHPExcel_Writer_Excel5_Parser return $token; } // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) - elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.')) { return $token; } - // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.')) { return $token; } - // if it's a range (A1:A2) - elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and - !preg_match("/[0-9]/",$this->_lookahead)) - { - return $token; - } - // if it's a range (A1..A2) - elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and + // if it's a range A1:A2 or $A$1:$A$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/', $token) and !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 - elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and !preg_match("/[0-9]/",$this->_lookahead)) { return $token; @@ -1235,7 +1222,7 @@ class PHPExcel_Writer_Excel5_Parser { $this->_current_char = 0; $this->_formula = $formula; - $this->_lookahead = $formula{1}; + $this->_lookahead = isset($formula{1}) ? $formula{1} : ''; $this->_advance(); $this->_parse_tree = $this->_condition(); return true; @@ -1389,29 +1376,30 @@ class PHPExcel_Writer_Excel5_Parser return $result; } // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) - elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } // if it's a range A1:B2 or $A$1:$B$2 - elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token) or - preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token)) + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token) or + preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token)) { - $result = $this->_current_token; + // must be an error? + $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) - elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) { // must be an error? //$result = $this->_current_token; @@ -1420,7 +1408,7 @@ class PHPExcel_Writer_Excel5_Parser return $result; } // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) { // must be an error? //$result = $this->_current_token; diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php index bdae49f5c..0b12fe52a 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php @@ -22,7 +22,7 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Workbook (used as the base for this class): @@ -33,7 +33,7 @@ // * The majority of this is _NOT_ my code. I simply ported it from the // * PERL Spreadsheet::WriteExcel module. // * -// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * The author of the Spreadsheet::WriteExcel module is John McNamara // * // * // * I _DO_ maintain this code, and John McNamara has nothing to do with the @@ -61,54 +61,6 @@ // */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Shared_Date */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Date.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_Shared_Escher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher.php'; - -/** PHPExcel_Shared_Escher_DggContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php'; - -/** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php'; - -/** PHPExcel_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; - -/** PHPExcel_Writer_Excel5_Xf */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Xf.php'; - -/** PHPExcel_Writer_Excel5_BIFFwriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/BIFFwriter.php'; - -/** PHPExcel_Writer_Excel5_Worksheet */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Worksheet.php'; - -/** PHPExcel_Writer_Excel5_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Font.php'; - -/** PHPExcel_Writer_Excel5_Escher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Escher.php'; - - /** * PHPExcel_Writer_Excel5_Workbook * @@ -130,7 +82,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * @var integer * @see _calcSheetOffsets() */ - var $_biffsize; + public $_biffsize; /** * XF Writers @@ -142,25 +94,19 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * Array containing the colour palette * @var array */ - var $_palette; + public $_palette; /** * The codepage indicates the text encoding used for strings * @var integer */ - var $_codepage; + public $_codepage; /** * The country code used for localization * @var integer */ - var $_country_code; - - /** - * The temporary dir for storing the OLE file - * @var string - */ - var $_tmp_dir; + public $_country_code; /** * Workbook @@ -249,7 +195,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ public function __construct(PHPExcel $phpExcel = null, $BIFF_version = 0x0600, &$str_total, - &$str_unique, &$str_table, &$colors, $parser, $tempDir = '' + &$str_unique, &$str_table, &$colors, $parser ) { // It needs to call its parent's constructor explicitly @@ -266,10 +212,9 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $this->_str_table = &$str_table; $this->_colors = &$colors; $this->_setPaletteXl97(); - $this->_tmp_dir = $tempDir; - + $this->_phpExcel = $phpExcel; - + if ($BIFF_version == 0x0600) { $this->_BIFF_version = 0x0600; // change BIFFwriter limit for CONTINUE records @@ -281,7 +226,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $countSheets = count($phpExcel->getAllSheets()); for ($i = 0; $i < $countSheets; ++$i) { $phpSheet = $phpExcel->getSheet($i); - + $this->_parser->setExtSheet($phpSheet->getTitle(), $i); // Register worksheet name with parser // for BIFF8 @@ -480,30 +425,30 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter public function writeWorkbook($pWorksheetSizes = null) { $this->_worksheetSizes = $pWorksheetSizes; - + // Calculate the number of selected worksheet tabs and call the finalization // methods for each worksheet $total_worksheets = count($this->_phpExcel->getAllSheets()); // Add part 1 of the Workbook globals, what goes before the SHEET records $this->_storeBof(0x0005); - $this->_storeCodepage(); + $this->_writeCodepage(); if ($this->_BIFF_version == 0x0600) { - $this->_storeWindow1(); + $this->_writeWindow1(); } if ($this->_BIFF_version == 0x0500) { - $this->_storeExterns(); // For print area and repeat rows - $this->_storeNames(); // For print area and repeat rows + $this->_writeExterns(); // For print area and repeat rows + $this->_writeNames(); // For print area and repeat rows } if ($this->_BIFF_version == 0x0500) { - $this->_storeWindow1(); + $this->_writeWindow1(); } - $this->_storeDatemode(); - $this->_storeAllFonts(); - $this->_storeAllNumFormats(); - $this->_storeAllXfs(); - $this->_storeAllStyles(); - $this->_storePalette(); + $this->_writeDatemode(); + $this->_writeAllFonts(); + $this->_writeAllNumFormats(); + $this->_writeAllXfs(); + $this->_writeAllStyles(); + $this->_writePalette(); // Prepare part 3 of the workbook global stream, what goes after the SHEET records $part3 = ''; @@ -527,12 +472,12 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // Add part 2 of the Workbook globals, the SHEET records $this->_calcSheetOffsets(); for ($i = 0; $i < $total_worksheets; ++$i) { - $this->_storeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); + $this->_writeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); } // Add part 3 of the Workbook globals $this->_data .= $part3; - + return $this->_data; } @@ -572,10 +517,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the Excel FONT records. - * - * @access private */ - function _storeAllFonts() + private function _writeAllFonts() { foreach ($this->_fontWriters as $fontWriter) { $this->_append($fontWriter->writeFont()); @@ -584,22 +527,18 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store user defined numerical formats i.e. FORMAT records - * - * @access private */ - function _storeAllNumFormats() + private function _writeAllNumFormats() { foreach ($this->_numberFormats as $numberFormatIndex => $numberFormat) { - $this->_storeNumFormat($numberFormat->getFormatCode(), $numberFormatIndex); + $this->_writeNumFormat($numberFormat->getFormatCode(), $numberFormatIndex); } } /** * Write all XF records. - * - * @access private */ - function _storeAllXfs() + private function _writeAllXfs() { foreach ($this->_xfWriters as $xfWriter) { $this->_append($xfWriter->writeXf()); @@ -608,37 +547,31 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write all STYLE records. - * - * @access private */ - function _storeAllStyles() + private function _writeAllStyles() { - $this->_storeStyle(); + $this->_writeStyle(); } /** * Write the EXTERNCOUNT and EXTERNSHEET records. These are used as indexes for * the NAME records. - * - * @access private */ - function _storeExterns() + private function _writeExterns() { // Create EXTERNCOUNT with number of worksheets - $this->_storeExterncount(count($this->_phpExcel->getAllSheets())); + $this->_writeExterncount(count($this->_phpExcel->getAllSheets())); // Create EXTERNSHEET for each worksheet foreach ($this->_phpExcel->getWorksheetIterator() as $sheet) { - $this->_storeExternsheet($sheet->getTitle()); + $this->_writeExternsheet($sheet->getTitle()); } } /** * Write the NAME record to define the print area and the repeat rows and cols. - * - * @access private */ - function _storeNames() + private function _writeNames() { // total number of sheets $total_worksheets = count($this->_phpExcel->getAllSheets()); @@ -652,13 +585,13 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $printArea = $printArea[0]; $printArea[0] = PHPExcel_Cell::coordinateFromString($printArea[0]); $printArea[1] = PHPExcel_Cell::coordinateFromString($printArea[1]); - + $print_rowmin = $printArea[0][1] - 1; $print_rowmax = $printArea[1][1] - 1; $print_colmin = PHPExcel_Cell::columnIndexFromString($printArea[0][0]) - 1; $print_colmax = PHPExcel_Cell::columnIndexFromString($printArea[1][0]) - 1; - $this->_storeNameShort( + $this->_writeNameShort( $i, // sheet index 0x06, // NAME type $print_rowmin, @@ -681,8 +614,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $repeat = $this->_phpExcel->getSheet($i)->getPageSetup()->getRowsToRepeatAtTop(); $rowmin = $repeat[0] - 1; $rowmax = $repeat[1] - 1; - - $this->_storeNameLong( + + $this->_writeNameLong( $i, // sheet index 0x07, // NAME type $rowmin, @@ -714,7 +647,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $rowmax = 16383; } - $this->_storeNameShort( + $this->_writeNameShort( $i, // sheet index 0x07, // NAME type $rowmin, @@ -740,7 +673,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // Loop named ranges $namedRanges = $this->_phpExcel->getNamedRanges(); foreach ($namedRanges as $namedRange) { - + // Create absolute coordinate $range = PHPExcel_Cell::splitRange($namedRange->getRange()); for ($i = 0; $i < count($range); $i++) { @@ -755,7 +688,20 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter try { $error = $this->_parser->parse($range); $formulaData = $this->_parser->toReversePolish(); - $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, 0, false)); + + // make sure tRef3d is of type tRef3dR (0x3A) + if (isset($formulaData{0}) and ($formulaData{0} == "\x7A" or $formulaData{0} == "\x5A")) { + $formulaData = "\x3A" . substr($formulaData, 1); + } + + if ($namedRange->getLocalOnly()) { + // local scope + $scope = $this->_phpExcel->getIndex($namedRange->getScope()) + 1; + } else { + // global scope + $scope = 0; + } + $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, $scope, false)); } catch(Exception $e) { // do nothing @@ -830,7 +776,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $printAreaRect = $printArea[$j]; // e.g. A3:J6 $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); - + $print_rowmin = $printAreaRect[0][1] - 1; $print_rowmax = $printAreaRect[1][1] - 1; $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; @@ -838,7 +784,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // construct formula data manually because parser does not recognize absolute 3d cell references $formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); - + if ($j > 0) { $formulaData .= pack('C', 0x10); // list operator token ',' } @@ -889,10 +835,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Stores the CODEPAGE biff record. - * - * @access private */ - function _storeCodepage() + private function _writeCodepage() { $record = 0x0042; // Record identifier $length = 0x0002; // Number of bytes to follow @@ -906,10 +850,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write Excel BIFF WINDOW1 record. - * - * @access private */ - function _storeWindow1() + private function _writeWindow1() { $record = 0x003D; // Record identifier $length = 0x0012; // Number of bytes to follow @@ -920,10 +862,10 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $dyWn = 0x1572; // Height of window $grbit = 0x0038; // Option flags - + // not supported by PHPExcel, so there is only one selected sheet, the active $ctabsel = 1; // Number of workbook tabs selected - + $wTabRatio = 0x0258; // Tab to scrollbar ratio // not supported by PHPExcel, set to 0 @@ -943,9 +885,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * * @param PHPExcel_Worksheet $sheet Worksheet name * @param integer $offset Location of worksheet BOF - * @access private */ - function _storeBoundsheet($sheet, $offset) + private function _writeBoundsheet($sheet, $offset) { $sheetname = $sheet->getTitle(); $record = 0x0085; // Record identifier @@ -1012,10 +953,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write Excel BIFF STYLE records. - * - * @access private */ - function _storeStyle() + private function _writeStyle() { $record = 0x0293; // Record identifier $length = 0x0004; // Bytes to follow @@ -1035,9 +974,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * * @param string $format Custom format string * @param integer $ifmt Format index code - * @access private */ - function _storeNumFormat($format, $ifmt) + private function _writeNumFormat($format, $ifmt) { $record = 0x041E; // Record identifier @@ -1062,10 +1000,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write DATEMODE record to indicate the date system in use (1904 or 1900). - * - * @access private */ - function _storeDatemode() + private function _writeDatemode() { $record = 0x0022; // Record identifier $length = 0x0002; // Bytes to follow @@ -1090,9 +1026,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * A similar method is used in Worksheet.php for a slightly different purpose. * * @param integer $cxals Number of external references - * @access private */ - function _storeExterncount($cxals) + private function _writeExterncount($cxals) { $record = 0x0016; // Record identifier $length = 0x0002; // Number of bytes to follow @@ -1111,9 +1046,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * A similar method is used in Worksheet.php for a slightly different purpose. * * @param string $sheetname Worksheet name - * @access private */ - function _storeExternsheet($sheetname) + private function _writeExternsheet($sheetname) { $record = 0x0017; // Record identifier $length = 0x02 + strlen($sheetname); // Number of bytes to follow @@ -1137,9 +1071,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $rowmax End row * @param integer $colmin Start colum * @param integer $colmax End column - * @access private */ - function _storeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax) + private function _writeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax) { $record = 0x0018; // Record identifier $length = 0x0024; // Number of bytes to follow @@ -1194,7 +1127,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the NAME record in the long format that is used for storing the repeat * rows and columns when both are specified. This shares a lot of code with - * _storeNameShort() but we use a separate method to keep the code clean. + * _writeNameShort() but we use a separate method to keep the code clean. * Code abstraction for reuse can be carried too far, and I should know. ;-) * * @param integer $index Sheet index @@ -1203,9 +1136,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $rowmax End row * @param integer $colmin Start colum * @param integer $colmax End column - * @access private */ - function _storeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax) + private function _writeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax) { $record = 0x0018; // Record identifier $length = 0x003d; // Number of bytes to follow @@ -1312,10 +1244,8 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Stores the PALETTE biff record. - * - * @access private */ - function _storePalette() + private function _writePalette() { $aref = $this->_palette; @@ -1551,6 +1481,15 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $blipData = file_get_contents($filename); break; + case 6: // Windows DIB (BMP), we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $imageResource = PHPExcel_Shared_Drawing::imagecreatefrombmp($filename); + ob_start(); + imagepng($imageResource); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + default: continue 2; } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php index 831740964..e70cbe926 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php @@ -22,7 +22,7 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class): @@ -33,7 +33,7 @@ // * The majority of this is _NOT_ my code. I simply ported it from the // * PERL Spreadsheet::WriteExcel module. // * -// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * The author of the Spreadsheet::WriteExcel module is John McNamara // * // * // * I _DO_ maintain this code, and John McNamara has nothing to do with the @@ -61,51 +61,6 @@ // */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Cell_DataType */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; - -/** PHPExcel_Writer_Excel5_Parser.php */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Parser.php'; - -/** PHPExcel_Writer_Excel5_BIFFwriter.php */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/BIFFwriter.php'; - -/** PHPExcel_Writer_Excel5_Escher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Escher.php'; - -/** PHPExcel_RichText */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; - -/** PHPExcel_Shared_Font */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_Shared_Excel5 */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Excel5.php'; - -/** PHPExcel_Shared_Escher */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher.php'; - -/** PHPExcel_Shared_Escher_DgContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer.php'; - -/** PHPExcel_Shared_Escher_DgContainer_SpgrContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php'; - -/** PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php'; - - /** * PHPExcel_Writer_Excel5_Worksheet * @@ -122,101 +77,77 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter */ private $_parser; - /** - * Filehandle to the temporary file for storing data - * @var resource - */ - var $_filehandle; - - /** - * Boolean indicating if we are using a temporary file for storing data - * @var bool - */ - var $_using_tmpfile; - /** * Maximum number of characters for a string (LABEL record in BIFF5) * @var integer */ - var $_xls_strmax; + public $_xls_strmax; /** * Array containing format information for columns * @var array */ - var $_colinfo; + public $_colinfo; /** * Array containing the selected area for the worksheet * @var array */ - var $_selection; + public $_selection; /** * The active pane for the worksheet * @var integer */ - var $_active_pane; + public $_active_pane; /** * Whether to use outline. * @var integer */ - var $_outline_on; + public $_outline_on; /** * Auto outline styles. * @var bool */ - var $_outline_style; + public $_outline_style; /** * Whether to have outline summary below. * @var bool */ - var $_outline_below; + public $_outline_below; /** * Whether to have outline summary at the right. * @var bool */ - var $_outline_right; + public $_outline_right; /** * Reference to the total number of strings in the workbook * @var integer */ - var $_str_total; + public $_str_total; /** * Reference to the number of unique strings in the workbook * @var integer */ - var $_str_unique; + public $_str_unique; /** * Reference to the array containing all the unique strings in the workbook * @var array */ - var $_str_table; + public $_str_table; /** * Color cache */ private $_colors; - /** - * The temporary dir for storing files - * @var string - */ - var $_tmp_dir; - - /** - * List of temporary files created - * @var array - */ - var $_tempFilesCreated = array(); - /** * Index of first used row (at least 0) * @var int @@ -268,7 +199,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter public function __construct($BIFF_version, &$str_total, &$str_unique, &$str_table, &$colors, - $parser, $tempDir = '', $preCalculateFormulas, $phpSheet) + $parser, $preCalculateFormulas, $phpSheet) { // It needs to call its parent's constructor explicitly parent::__construct(); @@ -286,13 +217,10 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_str_table = &$str_table; $this->_colors = &$colors; $this->_parser = $parser; - + $this->_phpSheet = $phpSheet; //$this->ext_sheets = array(); - $this->_filehandle = ''; - $this->_using_tmpfile = true; - //$this->fileclosed = 0; //$this->offset = 0; $this->_xls_strmax = 255; $this->_colinfo = array(); @@ -306,19 +234,16 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_outline_right = 1; $this->_outline_on = 1; - $this->_dv = array(); - - $this->_tmp_dir = $tempDir; - // calculate values for DIMENSIONS record $this->_firstRowIndex = 0; $this->_lastRowIndex = -1; $this->_firstColumnIndex = 0; $this->_lastColumnIndex = -1; - foreach ($this->_phpSheet->getCellCollection(false) as $cell) { - $row = $cell->getRow() - 1; - $column = PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1; + foreach ($this->_phpSheet->getCellCollection(false) as $cellID) { + preg_match('/^(\w+)(\d+)$/U',$cellID,$matches); + list(,$col,$row) = $matches; + $column = PHPExcel_Cell::columnIndexFromString($col) - 1; // Don't break Excel! if ($row + 1 > 65536 or $column + 1 > 256) { @@ -331,43 +256,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_lastColumnIndex = max($this->_lastColumnIndex, $column); } - $this->_initialize(); $this->_countCellStyleXfs = count($phpSheet->getParent()->getCellStyleXfCollection()); } - /** - * Cleanup - */ - public function cleanup() { - @fclose($this->_filehandle); - - foreach ($this->_tempFilesCreated as $file) { - @unlink($file); - } - } - - /** - * Open a tmp file to store the majority of the Worksheet data. If this fails, - * for example due to write permissions, store the data in memory. This can be - * slow for large files. - * - * @access private - */ - function _initialize() - { - // Open tmp file for storing Worksheet data - $fileName = tempnam($this->_tmp_dir, 'XLSHEET'); - $fh = fopen($fileName, 'w+'); - if ($fh) { - // Store filehandle - $this->_filehandle = $fh; - $this->_tempFilesCreated[] = $fileName; - } else { - // If tmpfile() fails store data in memory - $this->_using_tmpfile = false; - } - } - /** * Add data to the beginning of the workbook (note the reverse order) * and to the end of the workbook. @@ -382,8 +273,14 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Write BOF record $this->_storeBof(0x0010); - // Write DEFCOLWIDTH record - $this->_storeDefcol(); + // Write PRINTHEADERS + $this->_writePrintHeaders(); + + // Write PRINTGRIDLINES + $this->_writePrintGridlines(); + + // Write GRIDSET + $this->_writeGridset(); // Calculate column widths $this->_phpSheet->calculateColumnWidths(); @@ -412,81 +309,59 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs } - $this->_setColumn( $i, $i, $width, $xfIndex, $hidden, $level); + // Components of _colinfo: + // $firstcol first column on the range + // $lastcol last column on the range + // $width width to set + // $xfIndex The optional cell style Xf index to apply to the columns + // $hidden The optional hidden atribute + // $level The optional outline level + $this->_colinfo[] = array($i, $i, $width, $xfIndex, $hidden, $level); } - // Write the COLINFO records if they exist - if (!empty($this->_colinfo)) { - $colcount = count($this->_colinfo); - for ($i = 0; $i < $colcount; ++$i) { - $this->_storeColinfo($this->_colinfo[$i]); - } - } - - // Write EXTERNCOUNT of external references - if ($this->_BIFF_version == 0x0500) { - $this->_storeExterncount($num_sheets); - } - - // Write EXTERNSHEET references - if ($this->_BIFF_version == 0x0500) { - for ($i = 0; $i < $num_sheets; ++$i) { - $this->_storeExternsheet($this->_phpSheet->getParent()->getSheet($i)->getTitle()); - } - } - - // Write PRINTHEADERS - $this->_storePrintHeaders(); - - // Write PRINTGRIDLINES - $this->_storePrintGridlines(); - // Write GUTS - $this->_storeGuts(); - - // Write GRIDSET - $this->_storeGridset(); + $this->_writeGuts(); // Write DEFAULTROWHEIGHT if ($this->_BIFF_version == 0x0600) { - $this->_storeDefaultRowHeight(); + $this->_writeDefaultRowHeight(); } // Write WSBOOL - $this->_storeWsbool(); + $this->_writeWsbool(); // Write horizontal and vertical page breaks - $this->_storeBreaks(); + $this->_writeBreaks(); // Write page header - $this->_storeHeader(); + $this->_writeHeader(); // Write page footer - $this->_storeFooter(); + $this->_writeFooter(); // Write page horizontal centering - $this->_storeHcenter(); + $this->_writeHcenter(); // Write page vertical centering - $this->_storeVcenter(); + $this->_writeVcenter(); // Write left margin - $this->_storeMarginLeft(); + $this->_writeMarginLeft(); // Write right margin - $this->_storeMarginRight(); + $this->_writeMarginRight(); // Write top margin - $this->_storeMarginTop(); + $this->_writeMarginTop(); // Write bottom margin - $this->_storeMarginBottom(); + $this->_writeMarginBottom(); // Write page setup - $this->_storeSetup(); + $this->_writeSetup(); // Write sheet protection - $this->_storeProtect(); + $this->_writeProtect(); // Write SCENPROTECT $this->_writeScenProtect(); @@ -495,19 +370,43 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_writeObjectProtect(); // Write sheet password - $this->_storePassword(); + $this->_writePassword(); + + // Write DEFCOLWIDTH record + $this->_writeDefcol(); + + // Write the COLINFO records if they exist + if (!empty($this->_colinfo)) { + $colcount = count($this->_colinfo); + for ($i = 0; $i < $colcount; ++$i) { + $this->_writeColinfo($this->_colinfo[$i]); + } + } + + // Write EXTERNCOUNT of external references + if ($this->_BIFF_version == 0x0500) { + $this->_writeExterncount($num_sheets); + } + + // Write EXTERNSHEET references + if ($this->_BIFF_version == 0x0500) { + for ($i = 0; $i < $num_sheets; ++$i) { + $this->_writeExternsheet($this->_phpSheet->getParent()->getSheet($i)->getTitle()); + } + } // Write sheet dimensions - $this->_storeDimensions(); + $this->_writeDimensions(); // Row dimensions foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs - $this->_setRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); + $this->_writeRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); } // Write Cells - foreach ($this->_phpSheet->getCellCollection() as $cell) { + foreach ($this->_phpSheet->getCellCollection() as $cellID) { + $cell = $this->_phpSheet->getCell($cellID); $row = $cell->getRow() - 1; $column = PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1; @@ -518,7 +417,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Write cell value $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs - + if ($cell->getValue() instanceof PHPExcel_RichText) { $this->_writeString($row, $column, $cell->getValue()->getPlainText(), $xfIndex); } else { @@ -555,15 +454,15 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Append if ($this->_BIFF_version == 0x0600) { - $this->_storeMsoDrawing(); + $this->_writeMsoDrawing(); } - $this->_storeWindow2(); - $this->_storeZoom(); + $this->_writeWindow2(); + $this->_writeZoom(); if ($this->_phpSheet->getFreezePane()) { - $this->_storePanes(); + $this->_writePanes(); } - $this->_storeSelection(); - $this->_storeMergedCells(); + $this->_writeSelection(); + $this->_writeMergedCells(); // Hyperlinks if ($this->_BIFF_version == 0x0600) { @@ -584,19 +483,16 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // external (local file) $url = 'external:' . $url; } - + $this->_writeUrl($row - 1, PHPExcel_Cell::columnIndexFromString($column) - 1, $url); } } - /*if ($this->_BIFF_version == 0x0600) { - $this->_storeDataValidity(); - }*/ - if ($this->_BIFF_version == 0x0600) { - $this->_storeSheetLayout(); + $this->_writeDataValidity(); + $this->_writeSheetLayout(); $this->_writeSheetProtection(); - $this->_storeRangeProtection(); + $this->_writeRangeProtection(); } $this->_storeEof(); @@ -651,41 +547,12 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if (isset($this->_data)) { $tmp = $this->_data; unset($this->_data); - $fh = $this->_filehandle; - if ($this->_using_tmpfile) { - fseek($fh, 0); - } return $tmp; } - // Return data stored on disk - if ($this->_using_tmpfile) { - if ($tmp = fread($this->_filehandle, $buffer)) { - return $tmp; - } - } - // No data to return return false; } - /** - * Set the width of a single column or a range of columns. - * - * @param integer $firstcol first column on the range - * @param integer $lastcol last column on the range - * @param integer $width width to set - * @param integer $xfIndex The optional cell style Xf index to apply to the columns - * @param integer $hidden The optional hidden atribute - * @param integer $level The optional outline level - */ - private function _setColumn($firstcol, $lastcol, $width, $xfIndex = 15, $hidden = 0, $level = 0) - { - $this->_colinfo[] = array($firstcol, $lastcol, $width, $xfIndex, $hidden, $level); - - // Set width to zero if column is hidden - $width = ($hidden) ? 0 : $width; - } - /** * Set the option to print the row and column headers on the printed page. * @@ -697,27 +564,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_print_headers = $print; } - /** - * Store Worksheet data in memory using the parent's class append() or to a - * temporary file, the default. - * - * @access private - * @param string $data The binary data to append - */ - function _append($data) - { - if ($this->_using_tmpfile) { - // Add CONTINUE records if necessary - if (strlen($data) - 4 > $this->_limit) { - $data = $this->_addContinue($data); - } - fwrite($this->_filehandle, $data); - $this->_datasize += strlen($data); - } else { - parent::_append($data); - } - } - /** * This method sets the properties for outlining and grouping. The defaults * correspond to Excel's defaults. @@ -1002,8 +848,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Strip the '=' or '@' sign at the beginning of the formula string if (preg_match("/^=/", $formula)) { $formula = preg_replace("/(^=)/", "", $formula); - } elseif (preg_match("/^@/", $formula)) { - $formula = preg_replace("/(^@)/", "", $formula); } else { // Error handling $this->_writeString($row, $col, 'Unrecognised character for formula'); @@ -1317,7 +1161,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param bool $hidden The optional hidden attribute * @param integer $level The optional outline level for row, in range [0,7] */ - private function _setRow($row, $height, $xfIndex, $hidden = false, $level = 0) + private function _writeRow($row, $height, $xfIndex, $hidden = false, $level = 0) { $record = 0x0208; // Record identifier $length = 0x0010; // Number of bytes to follow @@ -1333,7 +1177,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $height = null; } - // Use _setRow($row, null, $XF) to set XF format without setting height + // Use _writeRow($row, null, $XF) to set XF format without setting height if ($height != null) { $miyRw = $height * 20; // row height } else { @@ -1366,10 +1210,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Writes Excel DIMENSIONS to define the area in which there is data. - * - * @access private */ - function _storeDimensions() + private function _writeDimensions() { $record = 0x0200; // Record identifier @@ -1400,10 +1242,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write BIFF record Window2. - * - * @access private */ - function _storeWindow2() + private function _writeWindow2() { $record = 0x023E; // Record identifier if ($this->_BIFF_version == 0x0500) { @@ -1420,7 +1260,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // The options flags that comprise $grbit $fDspFmla = 0; // 0 - bit $fDspGrid = $this->_phpSheet->getShowGridlines() ? 1 : 0; // 1 - $fDspRwCol = 1; // 2 + $fDspRwCol = $this->_phpSheet->getShowRowColHeaders() ? 1 : 0; // 2 $fFrozen = $this->_phpSheet->getFreezePane() ? 1 : 0; // 3 $fDspZeros = 1; // 4 $fDefaultHdr = 1; // 5 @@ -1460,10 +1300,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write BIFF record DEFAULTROWHEIGHT. - * - * @access private */ - private function _storeDefaultRowHeight() + private function _writeDefaultRowHeight() { $defaultRowHeight = $this->_phpSheet->getDefaultRowDimension()->getRowHeight(); @@ -1484,13 +1322,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write BIFF record DEFCOLWIDTH if COLINFO records are in use. - * - * @access private */ - function _storeDefcol() + private function _writeDefcol() { $defaultColWidth = 8; - + $record = 0x0055; // Record identifier $length = 0x0002; // Number of bytes to follow @@ -1505,7 +1341,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C * length record. * - * @access private * @param array $col_array This is the only parameter received and is composed of the following: * 0 => First formatted column, * 1 => Last formatted column, @@ -1514,7 +1349,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * 4 => Option flags. * 5 => Optional outline level */ - function _storeColinfo($col_array) + private function _writeColinfo($col_array) { if (isset($col_array[0])) { $colFirst = $col_array[0]; @@ -1543,28 +1378,26 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $level = 0; } $record = 0x007D; // Record identifier - $length = 0x000B; // Number of bytes to follow + $length = 0x000C; // Number of bytes to follow $coldx *= 256; // Convert to units of 1/256 of a char $ixfe = $xfIndex; - $reserved = 0x00; // Reserved + $reserved = 0x0000; // Reserved $level = max(0, min($level, 7)); $grbit |= $level << 8; $header = pack("vv", $record, $length); - $data = pack("vvvvvC", $colFirst, $colLast, $coldx, + $data = pack("vvvvvv", $colFirst, $colLast, $coldx, $ixfe, $grbit, $reserved); $this->_append($header.$data); } /** * Write BIFF record SELECTION. - * - * @access private */ - function _storeSelection() + private function _writeSelection() { // look up the selected cell range $selectedCells = $this->_phpSheet->getSelectedCells(); @@ -1576,7 +1409,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $first = $selectedCells[0]; $last = $selectedCells[0]; } - + list($colFirst, $rwFirst) = PHPExcel_Cell::coordinateFromString($first); $colFirst = PHPExcel_Cell::columnIndexFromString($colFirst) - 1; // base 0 column index --$rwFirst; // base 0 row index @@ -1584,7 +1417,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter list($colLast, $rwLast) = PHPExcel_Cell::coordinateFromString($last); $colLast = PHPExcel_Cell::columnIndexFromString($colLast) - 1; // base 0 column index --$rwLast; // base 0 row index - + // make sure we are not out of bounds $colFirst = min($colFirst, 255); $colLast = min($colLast, 255); @@ -1631,37 +1464,35 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the MERGEDCELLS records for all ranges of merged cells - * - * @access private */ - function _storeMergedCells() + private function _writeMergedCells() { $mergeCells = $this->_phpSheet->getMergeCells(); $countMergeCells = count($mergeCells); - + if ($countMergeCells == 0) { return; } - + // maximum allowed number of merged cells per record if ($this->_BIFF_version == 0x0600) { $maxCountMergeCellsPerRecord = 1027; } else { $maxCountMergeCellsPerRecord = 259; } - + // record identifier $record = 0x00E5; - + // counter for total number of merged cells treated so far by the writer $i = 0; - + // counter for number of merged cells written in record currently being written $j = 0; - + // initialize record data $recordData = ''; - + // loop through the merged cells foreach ($mergeCells as $mergeCell) { ++$i; @@ -1681,7 +1512,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $length = strlen($recordData); $header = pack('vv', $record, $length); $this->_append($header . $recordData); - + // initialize for next record, if any $recordData = ''; $j = 0; @@ -1692,7 +1523,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write SHEETLAYOUT record */ - private function _storeSheetLayout() + private function _writeSheetLayout() { if (!$this->_phpSheet->isTabColorSet()) { return; @@ -1715,7 +1546,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $header = pack('vv', $record, $length); $this->_append($header . $recordData); } - + /** * Write SHEETPROTECTION */ @@ -1759,14 +1590,14 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_append($header . $recordData); } - + /** * Write BIFF record RANGEPROTECTION - * + * * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records */ - private function _storeRangeProtection() + private function _writeRangeProtection() { foreach ($this->_phpSheet->getProtectedCells() as $range => $password) { // number of ranges, e.g. 'A1:B3 C20:D25' @@ -1818,10 +1649,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * complexity and eliminates the need for a two way dialogue between the formula * parser the worksheet objects. * - * @access private * @param integer $count The number of external sheet references in this worksheet */ - function _storeExterncount($count) + private function _writeExterncount($count) { $record = 0x0016; // Record identifier $length = 0x0002; // Number of bytes to follow @@ -1837,10 +1667,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * reference to all of the external worksheets the EXTERNSHEET index is the same * as the worksheet index. * - * @access private * @param string $sheetname The name of a external worksheet */ - function _storeExternsheet($sheetname) + private function _writeExternsheet($sheetname) { $record = 0x0017; // Record identifier @@ -1868,10 +1697,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * The panes can either be frozen or thawed (unfrozen). * Frozen panes are specified in terms of an integer number of rows and columns. * Thawed panes are specified in terms of Excel's units for rows and columns. - * - * @access private */ - function _storePanes() + private function _writePanes() { $panes = array(); if ($freezePane = $this->_phpSheet->getFreezePane()) { @@ -1882,7 +1709,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // thaw panes return; } - + $y = isset($panes[0]) ? $panes[0] : null; $x = isset($panes[1]) ? $panes[1] : null; $rwTop = isset($panes[2]) ? $panes[2] : null; @@ -1941,7 +1768,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } } - $this->_active_pane = $pnnAct; // Used in _storeSelection + $this->_active_pane = $pnnAct; // Used in _writeSelection $header = pack("vv", $record, $length); $data = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct); @@ -1950,10 +1777,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the page setup SETUP BIFF record. - * - * @access private */ - function _storeSetup() + private function _writeSetup() { $record = 0x00A1; // Record identifier $length = 0x0022; // Number of bytes to follow @@ -1969,9 +1794,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $grbit = 0x00; // Option flags $iRes = 0x0258; // Print resolution $iVRes = 0x0258; // Vertical print resolution - + $numHdr = $this->_phpSheet->getPageMargins()->getHeader(); // Header Margin - + $numFtr = $this->_phpSheet->getPageMargins()->getFooter(); // Footer Margin $iCopies = 0x01; // Number of copies @@ -2020,10 +1845,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the header caption BIFF record. - * - * @access private */ - function _storeHeader() + private function _writeHeader() { $record = 0x0014; // Record identifier @@ -2035,7 +1858,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $str = ''; } */ - + if ($this->_BIFF_version == 0x0600) { $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddHeader()); $length = strlen($recordData); @@ -2053,10 +1876,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the footer caption BIFF record. - * - * @access private */ - function _storeFooter() + private function _writeFooter() { $record = 0x0015; // Record identifier @@ -2068,7 +1889,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $str = ''; } */ - + if ($this->_BIFF_version == 0x0600) { $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddFooter()); $length = strlen($recordData); @@ -2089,7 +1910,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * * @access private */ - function _storeHcenter() + private function _writeHcenter() { $record = 0x0083; // Record identifier $length = 0x0002; // Bytes to follow @@ -2104,10 +1925,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the vertical centering VCENTER BIFF record. - * - * @access private */ - function _storeVcenter() + private function _writeVcenter() { $record = 0x0084; // Record identifier $length = 0x0002; // Bytes to follow @@ -2121,10 +1940,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the LEFTMARGIN BIFF record. - * - * @access private */ - function _storeMarginLeft() + private function _writeMarginLeft() { $record = 0x0026; // Record identifier $length = 0x0008; // Bytes to follow @@ -2142,10 +1959,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the RIGHTMARGIN BIFF record. - * - * @access private */ - function _storeMarginRight() + private function _writeMarginRight() { $record = 0x0027; // Record identifier $length = 0x0008; // Bytes to follow @@ -2163,10 +1978,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the TOPMARGIN BIFF record. - * - * @access private */ - function _storeMarginTop() + private function _writeMarginTop() { $record = 0x0028; // Record identifier $length = 0x0008; // Bytes to follow @@ -2184,10 +1997,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the BOTTOMMARGIN BIFF record. - * - * @access private */ - function _storeMarginBottom() + private function _writeMarginBottom() { $record = 0x0029; // Record identifier $length = 0x0008; // Bytes to follow @@ -2205,10 +2016,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write the PRINTHEADERS BIFF record. - * - * @access private */ - function _storePrintHeaders() + private function _writePrintHeaders() { $record = 0x002a; // Record identifier $length = 0x0002; // Bytes to follow @@ -2223,10 +2032,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the * GRIDSET record. - * - * @access private */ - function _storePrintGridlines() + private function _writePrintGridlines() { $record = 0x002b; // Record identifier $length = 0x0002; // Bytes to follow @@ -2241,10 +2048,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write the GRIDSET BIFF record. Must be used in conjunction with the * PRINTGRIDLINES record. - * - * @access private */ - function _storeGridset() + private function _writeGridset() { $record = 0x0082; // Record identifier $length = 0x0002; // Bytes to follow @@ -2261,10 +2066,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * where Excel outline symbols are displayed. The visibility of the gutters is * controlled by a flag in WSBOOL. * - * @see _storeWsbool() - * @access private + * @see _writeWsbool() */ - function _storeGuts() + private function _writeGuts() { $record = 0x0080; // Record identifier $length = 0x0008; // Bytes to follow @@ -2281,7 +2085,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $col_level = 0; // Calculate the maximum column outline level. The equivalent calculation - // for the row outline level is carried out in _setRow(). + // for the row outline level is carried out in _writeRow(). $colcount = count($this->_colinfo); for ($i = 0; $i < $colcount; ++$i) { $col_level = max($this->_colinfo[$i][5], $col_level); @@ -2308,10 +2112,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction * with the SETUP record. - * - * @access private */ - function _storeWsbool() + private function _writeWsbool() { $record = 0x0081; // Record identifier $length = 0x0002; // Bytes to follow @@ -2346,7 +2148,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records. */ - private function _storeBreaks() + private function _writeBreaks() { // initialize $vbreaks = array(); @@ -2374,7 +2176,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter break; } } - + //horizontal page breaks if (count($hbreaks) > 0) { @@ -2446,10 +2248,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Set the Biff PROTECT record to indicate that the worksheet is protected. - * - * @access private */ - function _storeProtect() + private function _writeProtect() { // Exit unless sheet protection has been specified if (!$this->_phpSheet->getProtection()->getSheet()) { @@ -2517,10 +2317,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write the worksheet PASSWORD record. - * - * @access private */ - function _storePassword() + private function _writePassword() { // Exit unless sheet protection and password have been specified if (!$this->_phpSheet->getProtection()->getSheet() || !$this->_phpSheet->getProtection()->getPassword()) { @@ -2676,7 +2474,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $x2 = $width / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object $y2 = $height / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) * 256; // Distance to bottom of object - $this->_storeObjPicture($col_start, $x1, + $this->_writeObjPicture($col_start, $x1, $row_start, $y1, $col_end, $x2, $row_end, $y2); @@ -2686,7 +2484,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * Store the OBJ record that precedes an IMDATA record. This could be generalise * to support other Excel objects. * - * @access private * @param integer $colL Column containing upper left corner of object * @param integer $dxL Distance from left side of cell * @param integer $rwT Row containing top left corner of object @@ -2696,7 +2493,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $rwB Row containing bottom right corner of object * @param integer $dyB Distance from bottom of cell */ - function _storeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB) + private function _writeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB) { $record = 0x005d; // Record identifier $length = 0x003c; // Bytes to follow @@ -2880,10 +2677,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Store the window zoom factor. This should be a reduced fraction but for * simplicity we will store all fractions with a numerator of 100. - * - * @access private */ - function _storeZoom() + private function _writeZoom() { // If scale is 100 we don't need to write a record if ($this->_phpSheet->getSheetView()->getZoomScale() == 100) { @@ -2901,7 +2696,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write MSODRAWING record */ - private function _storeMsoDrawing() + private function _writeMsoDrawing() { // check if there are any shapes for this sheet if (count($this->_phpSheet->getDrawingCollection()) == 0) { @@ -3034,34 +2829,163 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $header = pack('vv', $record, $length); $this->_append($header . $objData); } - + } /** - * Store the DVAL and DV records. - * - * @access private + * Store the DATAVALIDATIONS and DATAVALIDATION records. */ - function _storeDataValidity() + private function _writeDataValidity() { - $record = 0x01b2; // Record identifier + // Datavalidation collection + $dataValidationCollection = $this->_phpSheet->getDataValidationCollection(); + + // Write data validations? + if (count($dataValidationCollection) > 0) { + + // DATAVALIDATIONS record + $record = 0x01B2; // Record identifier $length = 0x0012; // Bytes to follow - $grbit = 0x0002; // Prompt box at cell, no cached validity data at DV records + $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position $verPos = 0x00000000; // Vertical position of prompt box, if fixed position - $objId = 0xffffffff; // Object identifier of drop down arrow object, or -1 if not visible + $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible $header = pack('vv', $record, $length); $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, - count($this->_dv)); + count($dataValidationCollection)); $this->_append($header.$data); - $record = 0x01be; // Record identifier - foreach ($this->_dv as $dv) { - $length = strlen($dv); // Bytes to follow + // DATAVALIDATION records + $record = 0x01BE; // Record identifier + + foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) { + // initialize record data + $data = ''; + + // options + $options = 0x00000000; + + // data type + $type = $dataValidation->getType(); + switch ($type) { + case PHPExcel_Cell_DataValidation::TYPE_NONE: $type = 0x00; break; + case PHPExcel_Cell_DataValidation::TYPE_WHOLE: $type = 0x01; break; + case PHPExcel_Cell_DataValidation::TYPE_DECIMAL: $type = 0x02; break; + case PHPExcel_Cell_DataValidation::TYPE_LIST: $type = 0x03; break; + case PHPExcel_Cell_DataValidation::TYPE_DATE: $type = 0x04; break; + case PHPExcel_Cell_DataValidation::TYPE_TIME: $type = 0x05; break; + case PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH: $type = 0x06; break; + case PHPExcel_Cell_DataValidation::TYPE_CUSTOM: $type = 0x07; break; + } + $options |= $type << 0; + + // error style + $errorStyle = $dataValidation->getType(); + switch ($errorStyle) { + case PHPExcel_Cell_DataValidation::STYLE_STOP: $errorStyle = 0x00; break; + case PHPExcel_Cell_DataValidation::STYLE_WARNING: $errorStyle = 0x01; break; + case PHPExcel_Cell_DataValidation::STYLE_INFORMATION: $errorStyle = 0x02; break; + } + $options |= $errorStyle << 4; + + // explicit formula? + if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) { + $options |= 0x01 << 7; + } + + // empty cells allowed + $options |= $dataValidation->getAllowBlank() << 8; + + // show drop down + $options |= (!$dataValidation->getShowDropDown()) << 9; + + // show input message + $options |= $dataValidation->getShowInputMessage() << 18; + + // show error message + $options |= $dataValidation->getShowErrorMessage() << 19; + + // condition operator + $operator = $dataValidation->getOperator(); + switch ($operator) { + case PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN: $operator = 0x00 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN: $operator = 0x01 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_EQUAL: $operator = 0x02 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL: $operator = 0x03 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN: $operator = 0x04 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN: $operator = 0x05 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL: $operator = 0x06; break; + case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL: $operator = 0x07 ; break; + } + $options |= $operator << 20; + + $data = pack('V', $options); + + // prompt title + $promptTitle = $dataValidation->getPromptTitle() !== '' ? + $dataValidation->getPromptTitle() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($promptTitle); + + // error title + $errorTitle = $dataValidation->getErrorTitle() !== '' ? + $dataValidation->getErrorTitle() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($errorTitle); + + // prompt text + $prompt = $dataValidation->getPrompt() !== '' ? + $dataValidation->getPrompt() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($prompt); + + // error text + $error = $dataValidation->getError() !== '' ? + $dataValidation->getError() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($error); + + // formula 1 + try { + $formula1 = $dataValidation->getFormula1(); + if ($type == 0x03) { // list type + $formula1 = str_replace(',', chr(0), $formula1); + } + $this->_parser->parse($formula1); + $formula1 = $this->_parser->toReversePolish(); + $sz1 = strlen($formula1); + + } catch(Exception $e) { + $sz1 = 0; + $formula1 = ''; + } + $data .= pack('vv', $sz1, 0x0000); + $data .= $formula1; + + // formula 2 + try { + $formula2 = $dataValidation->getFormula2(); + if ($formula2 === '') { + throw new Exception('No formula2'); + } + $this->_parser->parse($formula2); + $formula2 = $this->_parser->toReversePolish(); + $sz2 = strlen($formula2); + + } catch(Exception $e) { + $sz2 = 0; + $formula2 = ''; + } + $data .= pack('vv', $sz2, 0x0000); + $data .= $formula2; + + // cell range address list + $data .= pack('v', 0x0001); + $data .= $this->_writeBIFF8CellRangeAddressFixed($cellCoordinate); + + $length = strlen($data); $header = pack("vv", $record, $length); - $this->_append($header . $dv); + + $this->_append($header . $data); + } } } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php index be8d11ad8..8efd19037 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php @@ -22,7 +22,7 @@ * @package PHPExcel_Writer_Excel5 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Format (used as the base for this class): @@ -33,7 +33,7 @@ // * The majority of this is _NOT_ my code. I simply ported it from the // * PERL Spreadsheet::WriteExcel module. // * -// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * The author of the Spreadsheet::WriteExcel module is John McNamara // * // * // * I _DO_ maintain this code, and John McNamara has nothing to do with the @@ -61,27 +61,6 @@ // */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); -} - -/** PHPExcel_Style_Alignment */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Alignment.php'; - -/** PHPExcel_Style_Border */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Border.php'; - -/** PHPExcel_Style_Fill */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Fill.php'; - -/** PHPExcel_Style_Protection */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php'; - - /** * PHPExcel_Writer_Excel5_Xf * @@ -115,49 +94,49 @@ class PHPExcel_Writer_Excel5_Xf * An index (2 bytes) to a FORMAT record (number format). * @var integer */ - var $_numberFormatIndex; + public $_numberFormatIndex; /** * 1 bit, apparently not used. * @var integer */ - var $_text_justlast; + public $_text_justlast; /** * The cell's foreground color. * @var integer */ - var $_fg_color; + public $_fg_color; /** * The cell's background color. * @var integer */ - var $_bg_color; + public $_bg_color; /** * Color of the bottom border of the cell. * @var integer */ - var $_bottom_color; + public $_bottom_color; /** * Color of the top border of the cell. * @var integer */ - var $_top_color; + public $_top_color; /** * Color of the left border of the cell. * @var integer */ - var $_left_color; + public $_left_color; /** * Color of the right border of the cell. * @var integer */ - var $_right_color; + public $_right_color; /** * Constructor diff --git a/libraries/PHPExcel/PHPExcel/Writer/HTML.php b/libraries/PHPExcel/PHPExcel/Writer/HTML.php index 4ac8c73a6..90f96bddf 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/HTML.php +++ b/libraries/PHPExcel/PHPExcel/Writer/HTML.php @@ -22,37 +22,10 @@ * @package PHPExcel_Writer * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.2, 2010-01-11 + * @version 1.7.3, 2010-05-17 */ -/** PHPExcel root directory */ -if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); -} - -/** PHPExcel_IWriter */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; - -/** PHPExcel_Cell */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; - -/** PHPExcel_RichText */ -require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; - -/** PHPExcel_Shared_Drawing */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; - -/** PHPExcel_Shared_String */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; - -/** PHPExcel_HashTable */ -require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; - - /** * PHPExcel_Writer_HTML * @@ -88,14 +61,14 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * @var string */ private $_imagesRoot = '.'; - + /** * Use inline CSS? * * @var boolean */ private $_useInlineCss = false; - + /** * Array of CSS styles * @@ -184,7 +157,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Build CSS $this->buildCSS(!$this->_useInlineCss); - + // Open file $fileHandle = fopen($pFilename, 'w'); if ($fileHandle === false) { @@ -194,6 +167,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Write headers fwrite($fileHandle, $this->generateHTMLHeader(!$this->_useInlineCss)); + // Write navigation (tabs) + if (!$this->_isPdf) { + fwrite($fileHandle, $this->generateNavigation()); + } + // Write data fwrite($fileHandle, $this->generateSheetData()); @@ -349,9 +327,29 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; - // Loop through cells + // row min,max + $rowMin = $dimension[0][1]; + $rowMax = $dimension[1][1]; + + // calculate start of , + $tbodyStart = $rowMin; + $tbodyEnd = $rowMax; + $theadStart = 0; // default: no + $theadEnd = 0; // default: no + if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); + + // we can only support repeating rows that start at top row + if ($rowsToRepeatAtTop[0] == 1) { + $theadStart = $rowsToRepeatAtTop[0]; + $theadEnd = $rowsToRepeatAtTop[1]; + $tbodyStart = $rowsToRepeatAtTop[1] + 1; + } + } + + // Loop through cells $rowData = null; - for ($row = $dimension[0][1]; $row <= $dimension[1][1]; ++$row) { + for ($row = $rowMin; $row <= $rowMax; ++$row) { // Start a new row $rowData = array(); @@ -359,21 +357,41 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { for ($column = $dimension[0][0]; $column <= $dimension[1][0]; ++$column) { // Cell exists? if ($sheet->cellExistsByColumnAndRow($column, $row)) { - $rowData[$column] = $sheet->getCellByColumnAndRow($column, $row); + $rowData[$column] = $cell = $sheet->getCellByColumnAndRow($column, $row); } else { $rowData[$column] = ''; } } - // Write row if there are HTML table cells in it + // ? + if ($row == $theadStart) { + $html .= ' ' . "\r\n"; + } + + // ? + if ($row == $tbodyStart) { + $html .= ' ' . "\r\n"; + } + + // Write row if there are HTML table cells in it if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) { $html .= $this->_generateRow($sheet, $rowData, $row - 1); } + + // ? + if ($row == $theadEnd) { + $html .= ' ' . "\r\n"; + } + + // ? + if ($row == $tbodyEnd) { + $html .= ' ' . "\r\n"; + } } // Write table footer $html .= $this->_generateTableFooter(); - + // Writing PDF? if ($this->_isPdf) { @@ -381,7 +399,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $html .= ''; } } - + // Next sheet ++$sheetId; } @@ -390,6 +408,48 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $html; } + /** + * Generate sheet tabs + * + * @return string + * @throws Exception + */ + public function generateNavigation() + { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Construct HTML + $html = ''; + + // Only if there are more than 1 sheets + if (count($sheets) > 1) { + // Loop all sheets + $sheetId = 0; + + $html .= '' . "\r\n"; + } + + return $html; + } + /** * Generate image tag in cell * @@ -446,7 +506,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { if (is_null($this->_phpExcel)) { throw new Exception('Internal PHPExcel object not set to an instance of an object.'); } - + // Build CSS $css = $this->buildCSS($generateSurroundingHTML); @@ -458,7 +518,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $html .= '