From 8f7db244de93ddc2fc8afbf377cf2b6de84f83ba Mon Sep 17 00:00:00 2001
From: Mark Baker <mbaker@inviqa.com>
Date: Sun, 16 Jun 2013 10:26:16 +0100
Subject: [PATCH 1/7] Eliminate unnecessary version checks

---
 .../PHPExcel/Shared/OLE/ChainedBlockStream.php  | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php b/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php
index 64cecec..025c6cb 100644
--- a/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php
+++ b/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php
@@ -161,14 +161,15 @@ class PHPExcel_Shared_OLE_ChainedBlockStream
 	 */
 	public function stream_eof()
 	{
-		$eof = $this->pos >= strlen($this->data);
-		// Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508
-		if (version_compare(PHP_VERSION, '5.0', '>=') &&
-			version_compare(PHP_VERSION, '5.1', '<')) {
-
-		   $eof = !$eof;
-		}
-		return $eof;
+//		As we don't support below 5.2 anymore, this is simply redundancy and overhead
+//		$eof = $this->pos >= strlen($this->data);
+//		// Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508
+//		if (version_compare(PHP_VERSION, '5.0', '>=') &&
+//			version_compare(PHP_VERSION, '5.1', '<')) {
+//		   $eof = !$eof;
+//		}
+//		return $eof;
+		return $this->pos >= strlen($this->data);
 	}
 
 	/**

From a0859fd7d0a445fc2c67a5755ef7d0cdbbdb6b04 Mon Sep 17 00:00:00 2001
From: Mark Baker <mbaker@inviqa.com>
Date: Sun, 16 Jun 2013 15:13:05 +0100
Subject: [PATCH 2/7] Fix to number format masking for scientific notation

---
 Classes/PHPExcel/Style/NumberFormat.php       |  5 ++++-
 .../Calculation/TextData/TEXT.data            | 19 +++++++++++--------
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/Classes/PHPExcel/Style/NumberFormat.php b/Classes/PHPExcel/Style/NumberFormat.php
index 3d5b20e..80347bf 100644
--- a/Classes/PHPExcel/Style/NumberFormat.php
+++ b/Classes/PHPExcel/Style/NumberFormat.php
@@ -673,7 +673,10 @@ class PHPExcel_Style_NumberFormat extends PHPExcel_Style_Supervisor implements P
 									);
 							$value = preg_replace($number_regex, $value, $format);
 						} else {
-							if (preg_match('/0([^\d\.]+)0/', $format, $matches)) {
+							if (preg_match('/0E[+-]0/i', $format)) {
+								//	Scientific format
+								$value = sprintf('%5.2E', $value);
+							} elseif (preg_match('/0([^\d\.]+)0/', $format)) {
 								$value = self::_complexNumberFormatMask($value, $format);
 							} else {
 								$sprintf_pattern = "%0$minWidth." . strlen($right) . "f";
diff --git a/unitTests/rawTestData/Calculation/TextData/TEXT.data b/unitTests/rawTestData/Calculation/TextData/TEXT.data
index 3087dfa..da18def 100644
--- a/unitTests/rawTestData/Calculation/TextData/TEXT.data
+++ b/unitTests/rawTestData/Calculation/TextData/TEXT.data
@@ -1,10 +1,13 @@
-123.456,	'"$#,##0.00"',	"$123.46"
-123.456,	'"#,##0.00"',	"123.46"
-123.456,	'"#,##0"',	"123"
-123.456,	"00000",	"00123"
-123456.789,	'"$#,##0.00"',	'"$123,456.79"'
-123456.789,	'"#,##0.00"',	'"123,456.79"'
-123456.789,	"0.00E+00",	"1.23E05"
+123.456,		'"$#,##0.00"',	"$123.46"
+-123.456,		'"$#,##0.00"',	"$-123.46"
+123.456,		'"#,##0.00"',	"123.46"
+123.456,		'"#,##0"',		"123"
+123.456,		"00000",		"00123"
+123456.789,		'"$#,##0.00"',	'"$123,456.79"'
+123456.789,		'"#,##0.00"',	'"123,456.79"'
+123456.789,		"0.00E+00",		"1.23E05"
+-123456.789,	"0.00E+00",		"-1.23E05"
+0.000012345,	"0.00E+00",		"1.23E-05"
 "19-Dec-1960",	"yyyy-mm-dd",	"1960-12-19"
 "1-Jan-2012",	"yyyy-mm-dd",	"2012-01-01"
-1.75,		"# ?/?",	"1 3/4"
+1.75,			"# ?/?",		"1 3/4"

From 333c811c5e523544a60e0d004f4bd3cb6734dfcb Mon Sep 17 00:00:00 2001
From: Mark Baker <mbaker@inviqa.com>
Date: Sun, 16 Jun 2013 16:24:34 +0100
Subject: [PATCH 3/7] Minor performance tweaks to calculation engine

---
 Classes/PHPExcel/Calculation.php | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php
index a3f7be2..01cfb7c 100644
--- a/Classes/PHPExcel/Calculation.php
+++ b/Classes/PHPExcel/Calculation.php
@@ -3486,6 +3486,13 @@ class PHPExcel_Calculation {
 
 
 	private function _validateBinaryOperand($cellID, &$operand, &$stack) {
+		if (is_array($operand)) {
+			if ((count($operand, COUNT_RECURSIVE) - count($operand)) == 1) {
+				do {
+					$operand = array_pop($operand);
+				} while (is_array($operand));
+			}
+		}
 		//	Numbers, matrices and booleans can pass straight through, as they're already valid
 		if (is_string($operand)) {
 			//	We only need special validations for the operand if it is a string
@@ -3591,25 +3598,13 @@ class PHPExcel_Calculation {
 		if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return FALSE;
 		if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return FALSE;
 
-		$executeMatrixOperation = FALSE;
 		//	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_array($operand1)) || (is_array($operand2))) {
-			//	Ensure that both operands are arrays/matrices
-			$executeMatrixOperation = TRUE;
-			$mSize = array();
-			list($mSize[],$mSize[],$mSize[],$mSize[]) = self::_checkMatrixOperands($operand1,$operand2,2);
+			//	Ensure that both operands are arrays/matrices of the same size
+			self::_checkMatrixOperands($operand1, $operand2, 2);
 
-			//	But if they're both single cell matrices, then we can treat them as simple values
-			if (array_sum($mSize) == 4) {
-				$executeMatrixOperation = FALSE;
-				$operand1 = $operand1[0][0];
-				$operand2 = $operand2[0][0];
-			}
-		}
-
-		if ($executeMatrixOperation) {
 			try {
 				//	Convert operand 1 from a PHP array to a matrix
 				$matrix = new PHPExcel_Shared_JAMA_Matrix($operand1);

From 90eff17853bfbfce0502bae903a6fc9814ffa097 Mon Sep 17 00:00:00 2001
From: Mark Baker <mark@lange.demon.co.uk>
Date: Sun, 16 Jun 2013 21:34:17 +0100
Subject: [PATCH 4/7] Performance tweaks

---
 Classes/PHPExcel/Worksheet.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php
index 3094fb3..257fc7a 100644
--- a/Classes/PHPExcel/Worksheet.php
+++ b/Classes/PHPExcel/Worksheet.php
@@ -1054,7 +1054,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
      */
     public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $returnCell = false)
     {
-        $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValue($pValue);
+        $cell = $this->getCellByColumnAndRow($pColumn, $pRow)->setValue($pValue);
         return ($returnCell) ? $cell : $this;
     }
 
@@ -1086,7 +1086,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
      */
     public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false)
     {
-        $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType);
+        $cell = $this->getCellByColumnAndRow($pColumn, $pRow)->setValueExplicit($pValue, $pDataType);
         return ($returnCell) ? $cell : $this;
     }
 

From 6216d2855cac16c6adcd8f8f39bb81fd163c9cea Mon Sep 17 00:00:00 2001
From: Mark Baker <mark@lange.demon.co.uk>
Date: Sun, 16 Jun 2013 21:35:35 +0100
Subject: [PATCH 5/7] Performance tweaks

---
 Classes/PHPExcel/Worksheet.php | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php
index 3094fb3..19d8953 100644
--- a/Classes/PHPExcel/Worksheet.php
+++ b/Classes/PHPExcel/Worksheet.php
@@ -1142,18 +1142,15 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
             $this->_cachedHighestRow = max($this->_cachedHighestRow,$aCoordinates[1]);
 
             // Cell needs appropriate xfIndex
-            $rowDimensions    = $this->getRowDimensions();
-            $columnDimensions = $this->getColumnDimensions();
+            $rowDimension    = $this->getRowDimension($aCoordinates[1], FALSE);
+            $columnDimension = $this->getColumnDimension($aCoordinates[0], FALSE);
 
-            if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) {
+            if ($rowDimension !== NULL && $rowDimension->getXfIndex() > 0) {
                 // then there is a row dimension with explicit style, assign it to the cell
-                $cell->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex());
-            } else if ( isset($columnDimensions[$aCoordinates[0]]) ) {
+                $cell->setXfIndex($rowDimension->getXfIndex());
+            } elseif ($columnDimension !== NULL && $columnDimension->getXfIndex() > 0) {
                 // then there is a column dimension, assign it to the cell
-                $cell->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex());
-            } else {
-                // set to default index
-                $cell->setXfIndex(0);
+                $cell->setXfIndex($columnDimension->getXfIndex());
             }
 
             return $cell;
@@ -1253,13 +1250,15 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
      * @param int $pRow Numeric index of the row
      * @return PHPExcel_Worksheet_RowDimension
      */
-    public function getRowDimension($pRow = 1)
+    public function getRowDimension($pRow = 1, $create = TRUE)
     {
         // Found
         $found = null;
 
         // Get row dimension
         if (!isset($this->_rowDimensions[$pRow])) {
+			if (!$create)
+				return NULL;
             $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow);
 
             $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow);
@@ -1273,13 +1272,15 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
      * @param string $pColumn String index of the column
      * @return PHPExcel_Worksheet_ColumnDimension
      */
-    public function getColumnDimension($pColumn = 'A')
+    public function getColumnDimension($pColumn = 'A', $create = TRUE)
     {
         // Uppercase coordinate
         $pColumn = strtoupper($pColumn);
 
         // Fetch dimensions
         if (!isset($this->_columnDimensions[$pColumn])) {
+			if (!$create)
+				return NULL;
             $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn);
 
             if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn))

From 98e5ac2b240471d08586ed6798589c8ee903af30 Mon Sep 17 00:00:00 2001
From: Mark Baker <mark@lange.demon.co.uk>
Date: Mon, 17 Jun 2013 11:37:29 +0100
Subject: [PATCH 6/7] Performance improvements

---
 Classes/PHPExcel/Worksheet.php | 87 ++++++++++++++++++----------------
 1 file changed, 47 insertions(+), 40 deletions(-)

diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php
index 338dcca..bd5dc17 100644
--- a/Classes/PHPExcel/Worksheet.php
+++ b/Classes/PHPExcel/Worksheet.php
@@ -1123,38 +1123,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
         // Uppercase coordinate
         $pCoordinate = strtoupper($pCoordinate);
 
-        if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) {
+        if (strpos($pCoordinate, ':') !== false || strpos($pCoordinate, ',') !== false) {
             throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.');
-        } elseif (strpos($pCoordinate,'$') !== false) {
+        } elseif (strpos($pCoordinate, '$') !== false) {
             throw new PHPExcel_Exception('Cell coordinate must not be absolute.');
-        } else {
-            // Create new cell object
-
-            // Coordinates
-            $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate);
-
-			$cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this));
-            $this->_cellCollectionIsSorted = false;
-
-            if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0]))
-                $this->_cachedHighestColumn = $aCoordinates[0];
-
-            $this->_cachedHighestRow = max($this->_cachedHighestRow,$aCoordinates[1]);
-
-            // Cell needs appropriate xfIndex
-            $rowDimension    = $this->getRowDimension($aCoordinates[1], FALSE);
-            $columnDimension = $this->getColumnDimension($aCoordinates[0], FALSE);
-
-            if ($rowDimension !== NULL && $rowDimension->getXfIndex() > 0) {
-                // then there is a row dimension with explicit style, assign it to the cell
-                $cell->setXfIndex($rowDimension->getXfIndex());
-            } elseif ($columnDimension !== NULL && $columnDimension->getXfIndex() > 0) {
-                // then there is a column dimension, assign it to the cell
-                $cell->setXfIndex($columnDimension->getXfIndex());
-            }
-
-            return $cell;
         }
+
+        // Create new cell object
+        return $this->_createNewCell($pCoordinate);
     }
 
     /**
@@ -1169,21 +1145,52 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
         $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn);
         $coordinate = $columnLetter . $pRow;
 
-        if (!$this->_cellCollection->isDataSet($coordinate)) {
-            $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this));
-            $this->_cellCollectionIsSorted = false;
-
-            if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn)
-                $this->_cachedHighestColumn = $columnLetter;
-
-            $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow);
-
-            return $cell;
+        if ($this->_cellCollection->isDataSet($coordinate)) {
+            return $this->_cellCollection->getCacheData($coordinate);
         }
 
-        return $this->_cellCollection->getCacheData($coordinate);
+		return $this->_createNewCell($coordinate);
     }
 
+    /**
+     * Create a new cell at the specified coordinate
+     *
+     * @param string $pCoordinate    Coordinate of the cell
+     * @return PHPExcel_Cell Cell that was created
+     */
+	private function _createNewCell($pCoordinate)
+	{
+		$cell = $this->_cellCollection->addCacheData(
+			$pCoordinate,
+			new PHPExcel_Cell(
+				NULL, 
+				PHPExcel_Cell_DataType::TYPE_NULL, 
+				$this
+			)
+		);
+        $this->_cellCollectionIsSorted = false;
+
+        // Coordinates
+        $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate);
+        if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0]))
+            $this->_cachedHighestColumn = $aCoordinates[0];
+        $this->_cachedHighestRow = max($this->_cachedHighestRow, $aCoordinates[1]);
+
+        // Cell needs appropriate xfIndex
+        $rowDimension    = $this->getRowDimension($aCoordinates[1], FALSE);
+        $columnDimension = $this->getColumnDimension($aCoordinates[0], FALSE);
+
+        if ($rowDimension !== NULL && $rowDimension->getXfIndex() > 0) {
+            // then there is a row dimension with explicit style, assign it to the cell
+            $cell->setXfIndex($rowDimension->getXfIndex());
+        } elseif ($columnDimension !== NULL && $columnDimension->getXfIndex() > 0) {
+            // then there is a column dimension, assign it to the cell
+            $cell->setXfIndex($columnDimension->getXfIndex());
+        }
+
+        return $cell;
+	}
+	
     /**
      * Cell at a specific coordinate exists?
      *

From da7cd71be894aabb8d5b70e820e3c9ffec38ea70 Mon Sep 17 00:00:00 2001
From: Mark Baker <mark@lange.demon.co.uk>
Date: Mon, 17 Jun 2013 12:01:51 +0100
Subject: [PATCH 7/7] Minor performance tweaks

---
 Classes/PHPExcel/Worksheet.php | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php
index bd5dc17..4c7b239 100644
--- a/Classes/PHPExcel/Worksheet.php
+++ b/Classes/PHPExcel/Worksheet.php
@@ -1176,7 +1176,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
             $this->_cachedHighestColumn = $aCoordinates[0];
         $this->_cachedHighestRow = max($this->_cachedHighestRow, $aCoordinates[1]);
 
-        // Cell needs appropriate xfIndex
+        // Cell needs appropriate xfIndex from dimensions records
+		//    but don't create dimension records if they don't already exist
         $rowDimension    = $this->getRowDimension($aCoordinates[1], FALSE);
         $columnDimension = $this->getColumnDimension($aCoordinates[0], FALSE);
 
@@ -1192,7 +1193,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	}
 	
     /**
-     * Cell at a specific coordinate exists?
+     * Does the cell at a specific coordinate exist?
      *
      * @param string $pCoordinate  Coordinate of the cell
      * @throws PHPExcel_Exception