From b98f27f4a7fb8f95546480c83779d72cf46837ea Mon Sep 17 00:00:00 2001
From: Mark Baker <mark@lange.demon.co.uk>
Date: Mon, 26 Nov 2012 18:01:15 +0000
Subject: [PATCH] Performance and memory improvements to Excel5 OLE Reader
 Temporary fix to XML flush until I get it working correctly Use of
 PHPExcel_Exception

---
 Classes/PHPExcel.php                          | 47 ++++++++++---------
 Classes/PHPExcel/Cell.php                     |  5 +-
 Classes/PHPExcel/HashTable.php                |  6 +--
 Classes/PHPExcel/NamedRange.php               |  3 +-
 Classes/PHPExcel/Shared/OLERead.php           | 41 ++++++++--------
 Classes/PHPExcel/Worksheet.php                | 29 +++++-------
 .../PHPExcel/Writer/Excel2007/Worksheet.php   |  2 +-
 7 files changed, 66 insertions(+), 67 deletions(-)

diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php
index a402214..8d4101c 100644
--- a/Classes/PHPExcel.php
+++ b/Classes/PHPExcel.php
@@ -196,7 +196,7 @@ class PHPExcel
      *
      * @param  int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
      * @return PHPExcel_Worksheet
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function createSheet($iSheetIndex = NULL)
     {
@@ -222,12 +222,12 @@ class PHPExcel
      * @param  PHPExcel_Worksheet $pSheet
      * @param  int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
      * @return PHPExcel_Worksheet
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = NULL)
     {
         if ($this->sheetNameExists($pSheet->getTitle())) {
-            throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first.");
+            throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first.");
         }
 
         if($iSheetIndex === NULL) {
@@ -256,12 +256,12 @@ class PHPExcel
      * Remove sheet by index
      *
      * @param  int $pIndex Active sheet index
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function removeSheetByIndex($pIndex = 0)
     {
         if ($pIndex > count($this->_workSheetCollection) - 1) {
-            throw new Exception("Sheet index is out of bounds.");
+            throw new PHPExcel_Exception("Sheet index is out of bounds.");
         } else {
             array_splice($this->_workSheetCollection, $pIndex, 1);
         }
@@ -278,12 +278,12 @@ class PHPExcel
      *
      * @param  int $pIndex Sheet index
      * @return PHPExcel_Worksheet
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function getSheet($pIndex = 0)
     {
         if ($pIndex > count($this->_workSheetCollection) - 1) {
-            throw new Exception("Sheet index is out of bounds.");
+            throw new PHPExcel_Exception("Sheet index is out of bounds.");
         } else {
             return $this->_workSheetCollection[$pIndex];
         }
@@ -304,7 +304,6 @@ class PHPExcel
      *
      * @param  string $pName Sheet name
      * @return PHPExcel_Worksheet
-     * @throws Exception
      */
     public function getSheetByName($pName = '')
     {
@@ -315,7 +314,7 @@ class PHPExcel
             }
         }
 
-        return null;
+        return NULL;
     }
 
     /**
@@ -323,7 +322,7 @@ class PHPExcel
      *
      * @param  PHPExcel_Worksheet $pSheet
      * @return Sheet index
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function getIndex(PHPExcel_Worksheet $pSheet)
     {
@@ -332,6 +331,8 @@ class PHPExcel
                 return $key;
             }
         }
+
+        throw new PHPExcel_Exception("Sheet does not exist.");
     }
 
     /**
@@ -340,7 +341,7 @@ class PHPExcel
      * @param  string $sheetName Sheet name to modify index for
      * @param  int $newIndex New index for the sheet
      * @return New sheet index
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function setIndexByName($sheetName, $newIndex)
     {
@@ -383,13 +384,13 @@ class PHPExcel
      * Set active sheet index
      *
      * @param  int $pIndex Active sheet index
-     * @throws Exception
+     * @throws PHPExcel_Exception
      * @return PHPExcel_Worksheet
      */
     public function setActiveSheetIndex($pIndex = 0)
     {
         if ($pIndex > count($this->_workSheetCollection) - 1) {
-            throw new Exception("Active sheet index is out of bounds.");
+            throw new PHPExcel_Exception("Active sheet index is out of bounds.");
         } else {
             $this->_activeSheetIndex = $pIndex;
         }
@@ -401,7 +402,7 @@ class PHPExcel
      *
      * @param  string $pValue Sheet title
      * @return PHPExcel_Worksheet
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function setActiveSheetIndexByName($pValue = '')
     {
@@ -410,7 +411,7 @@ class PHPExcel
             return $worksheet;
         }
 
-        throw new Exception('Workbook does not contain sheet:' . $pValue);
+        throw new PHPExcel_Exception('Workbook does not contain sheet:' . $pValue);
     }
 
     /**
@@ -434,12 +435,12 @@ class PHPExcel
      *
      * @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
+     * @throws PHPExcel_Exception
      * @return PHPExcel_Worksheet
      */
     public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) {
         if ($this->sheetNameExists($pSheet->getTitle())) {
-            throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
+            throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
         }
 
         // count how many cellXfs there are in this workbook currently, we will need this below
@@ -622,14 +623,14 @@ class PHPExcel
      * Get default style
      *
      * @return PHPExcel_Style
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function getDefaultStyle()
     {
         if (isset($this->_cellXfCollection[0])) {
             return $this->_cellXfCollection[0];
         }
-        throw new Exception('No default style found for this workbook');
+        throw new PHPExcel_Exception('No default style found for this workbook');
     }
 
     /**
@@ -647,12 +648,12 @@ class PHPExcel
      * Remove cellXf by index. It is ensured that all cells get their xf index updated.
      *
      * @param  int $pIndex Index to cellXf
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function removeCellXfByIndex($pIndex = 0)
     {
         if ($pIndex > count($this->_cellXfCollection) - 1) {
-            throw new Exception("CellXf index is out of bounds.");
+            throw new PHPExcel_Exception("CellXf index is out of bounds.");
         } else {
             // first remove the cellXf
             array_splice($this->_cellXfCollection, $pIndex, 1);
@@ -736,12 +737,12 @@ class PHPExcel
      * Remove cellStyleXf by index
      *
      * @param int $pIndex
-     * @throws Exception
+     * @throws PHPExcel_Exception
      */
     public function removeCellStyleXfByIndex($pIndex = 0)
     {
         if ($pIndex > count($this->_cellStyleXfCollection) - 1) {
-            throw new Exception("CellStyleXf index is out of bounds.");
+            throw new PHPExcel_Exception("CellStyleXf index is out of bounds.");
         } else {
             array_splice($this->_cellStyleXfCollection, $pIndex, 1);
         }
diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php
index d858c8a..9504446 100644
--- a/Classes/PHPExcel/Cell.php
+++ b/Classes/PHPExcel/Cell.php
@@ -727,7 +727,6 @@ class PHPExcel_Cell
 	 *
 	 *	@param	string $pString
 	 *	@return	int Column index (base 1 !!!)
-	 *	@throws	Exception
 	 */
 	public static function columnIndexFromString($pString = 'A')
 	{
@@ -894,11 +893,11 @@ class PHPExcel_Cell
 	 * Set value binder to use
 	 *
 	 * @param PHPExcel_Cell_IValueBinder $binder
-	 * @throws Exception
+	 * @throws PHPExcel_Exception
 	 */
 	public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = NULL) {
 		if ($binder === NULL) {
-			throw new Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly.");
+			throw new PHPExcel_Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly.");
 		}
 
 		self::$_valueBinder = $binder;
diff --git a/Classes/PHPExcel/HashTable.php b/Classes/PHPExcel/HashTable.php
index 0edc262..a47c4b1 100644
--- a/Classes/PHPExcel/HashTable.php
+++ b/Classes/PHPExcel/HashTable.php
@@ -53,7 +53,7 @@ class PHPExcel_HashTable
 	 * Create a new PHPExcel_HashTable
 	 *
 	 * @param	PHPExcel_IComparable[] $pSource	Optional source array to create HashTable from
-	 * @throws	Exception
+	 * @throws	PHPExcel_Exception
 	 */
 	public function __construct($pSource = null)
 	{
@@ -67,14 +67,14 @@ class PHPExcel_HashTable
 	 * Add HashTable items from source
 	 *
 	 * @param	PHPExcel_IComparable[] $pSource	Source array to create HashTable from
-	 * @throws	Exception
+	 * @throws	PHPExcel_Exception
 	 */
 	public function addFromSource($pSource = null) {
 		// Check if an array was passed
 		if ($pSource == null) {
 			return;
 		} else if (!is_array($pSource)) {
-			throw new Exception('Invalid array parameter passed.');
+			throw new PHPExcel_Exception('Invalid array parameter passed.');
 		}
 
 		foreach ($pSource as $item) {
diff --git a/Classes/PHPExcel/NamedRange.php b/Classes/PHPExcel/NamedRange.php
index 43a5fec..4b58df4 100644
--- a/Classes/PHPExcel/NamedRange.php
+++ b/Classes/PHPExcel/NamedRange.php
@@ -78,12 +78,13 @@ class PHPExcel_NamedRange
      * @param string $pRange
      * @param bool $pLocalOnly
      * @param PHPExcel_Worksheet|null $pScope	Scope. Only applies when $pLocalOnly = true. Null for global scope.
+     * @throws PHPExcel_Exception
      */
     public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null)
     {
     	// Validate data
     	if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) {
-    		throw new Exception('Parameters can not be null.');
+    		throw new PHPExcel_Exception('Parameters can not be null.');
     	}
 
     	// Set local members
diff --git a/Classes/PHPExcel/Shared/OLERead.php b/Classes/PHPExcel/Shared/OLERead.php
index be672b1..336cf5a 100644
--- a/Classes/PHPExcel/Shared/OLERead.php
+++ b/Classes/PHPExcel/Shared/OLERead.php
@@ -131,34 +131,26 @@ class PHPExcel_Shared_OLERead {
 			}
 		}
 
-		$pos = $index = 0;
-		$this->bigBlockChain = array();
-
+		$pos = 0;
+		$this->bigBlockChain = '';
 		$bbs = self::BIG_BLOCK_SIZE / 4;
 		for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
 			$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
 
-			for ($j = 0 ; $j < $bbs; ++$j) {
-				$this->bigBlockChain[$index] = self::_GetInt4d($this->data, $pos);
-				$pos += 4 ;
-				++$index;
-			}
+			$this->bigBlockChain .= substr($this->data, $pos, 4*$bbs);
+			$pos += 4*$bbs;
 		}
 
-		$pos = $index = 0;
+		$pos = 0;
 		$sbdBlock = $this->sbdStartBlock;
-		$this->smallBlockChain = array();
-
+		$this->smallBlockChain = '';
 		while ($sbdBlock != -2) {
 			$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
 
-			for ($j = 0; $j < $bbs; ++$j) {
-				$this->smallBlockChain[$index] = self::_GetInt4d($this->data, $pos);
-				$pos += 4;
-				++$index;
-			}
+			$this->smallBlockChain .= substr($this->data, $pos, 4*$bbs);
+			$pos += 4*$bbs;
 
-			$sbdBlock = $this->bigBlockChain[$sbdBlock];
+			$sbdBlock = self::_GetInt4d($this->bigBlockChain, $sbdBlock*4);
 		}
 
 		// read the directory stream
@@ -190,7 +182,10 @@ class PHPExcel_Shared_OLERead {
 	  			$pos = $block * self::SMALL_BLOCK_SIZE;
 				$streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE);
 
-				$block = $this->smallBlockChain[$block];
+//				$block = $this->smallBlockChain[$block];
+//				$block = unpack('l', substr($this->smallBlockChain, $block*4, 4));
+//				$block = $block[1];
+				$block = self::_GetInt4d($this->smallBlockChain, $block*4);
 			}
 
 			return $streamData;
@@ -207,7 +202,10 @@ class PHPExcel_Shared_OLERead {
 			while ($block != -2) {
 				$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
 				$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
-				$block = $this->bigBlockChain[$block];
+//				$block = $this->bigBlockChain[$block];
+//				$block = unpack('l', substr($this->bigBlockChain, $block*4, 4));
+//				$block = $block[1];
+				$block = self::_GetInt4d($this->bigBlockChain, $block*4);
 			}
 
 			return $streamData;
@@ -228,7 +226,10 @@ class PHPExcel_Shared_OLERead {
 		while ($block != -2)  {
 			$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
 			$data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
-			$block = $this->bigBlockChain[$block];
+//			$block = $this->bigBlockChain[$block];
+//			$block = unpack('l', substr($this->bigBlockChain, $block*4, 4));
+//			$block = $block[1];
+			$block = self::_GetInt4d($this->bigBlockChain, $block*4);
 		}
 		return $data;
 	 }
diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php
index 4ffd94f..c54e7f6 100644
--- a/Classes/PHPExcel/Worksheet.php
+++ b/Classes/PHPExcel/Worksheet.php
@@ -409,18 +409,18 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 *
 	 * @param string $pValue The string to check
 	 * @return string The valid string
-	 * @throws Exception
+	 * @throws PHPExcel_Exception
 	 */
 	private static function _checkSheetTitle($pValue)
 	{
 		// Some of the printable ASCII characters are invalid:  * : / \ ? [ ]
 		if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) {
-			throw new Exception('Invalid character found in sheet title');
+			throw new PHPExcel_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.');
+			throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet title.');
 		}
 
 		return $pValue;
@@ -523,7 +523,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 * @param PHPExcel_Chart $pChart
 	 * @param int|null $iChartIndex Index where chart should go (0,1,..., or null for last)
 	 * @return PHPExcel_Chart
-	 * @throws Exception
 	 */
 	public function addChart(PHPExcel_Chart $pChart = null, $iChartIndex = null)
 	{
@@ -542,7 +541,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 * Return the count of charts on this worksheet
 	 *
 	 * @return int		The number of charts
-	 * @throws Exception
 	 */
 	public function getChartCount()
 	{
@@ -1081,7 +1079,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 * Get cell at a specific coordinate
 	 *
 	 * @param	string			$pCoordinate	Coordinate of the cell
-	 * @throws	Exception
+	 * @throws	PHPExcel_Exception
 	 * @return	PHPExcel_Cell	Cell that was found
 	 */
 	public function getCell($pCoordinate = 'A1')
@@ -1111,9 +1109,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 		$pCoordinate = strtoupper($pCoordinate);
 
 		if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) {
-			throw new Exception('Cell coordinate can not be a range of cells.');
+			throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.');
 		} elseif (strpos($pCoordinate,'$') !== false) {
-			throw new Exception('Cell coordinate must not be absolute.');
+			throw new PHPExcel_Exception('Cell coordinate must not be absolute.');
 		} else {
 			// Create new cell object
 
@@ -1178,7 +1176,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 * Cell at a specific coordinate exists?
 	 *
 	 * @param	string			$pCoordinate	Coordinate of the cell
-	 * @throws	Exception
+	 * @throws	PHPExcel_Exception
 	 * @return	boolean
 	 */
 	public function cellExists($pCoordinate = 'A1')
@@ -1210,9 +1208,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 		$pCoordinate = strtoupper($pCoordinate);
 
 		if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) {
-			throw new Exception('Cell coordinate can not be a range of cells.');
+			throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.');
 		} elseif (strpos($pCoordinate,'$') !== false) {
-			throw new Exception('Cell coordinate must not be absolute.');
+			throw new PHPExcel_Exception('Cell coordinate must not be absolute.');
 		} else {
 			// Coordinates
 			$aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate);
@@ -1508,14 +1506,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 *
 	 * @param	array of PHPExcel_Style_Conditional	$pCellStyle	Cell style to duplicate
 	 * @param	string								$pRange		Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1")
-	 * @throws	Exception
+	 * @throws	PHPExcel_Exception
 	 * @return PHPExcel_Worksheet
 	 */
 	public function duplicateConditionalStyle(array $pCellStyle = null, $pRange = '')
 	{
 		foreach($pCellStyle as $cellStyle) {
 			if (!($cellStyle instanceof PHPExcel_Style_Conditional)) {
-				throw new Exception('Style is not a conditional style');
+				throw new PHPExcel_Exception('Style is not a conditional style');
 			}
 		}
 
@@ -1582,7 +1580,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 *
 	 * @param	string			$pCell		Cell coordinate (e.g. A1)
 	 * @param	int				$pBreak		Break type (type of PHPExcel_Worksheet::BREAK_*)
-	 * @throws	Exception
+	 * @throws	PHPExcel_Exception
 	 * @return PHPExcel_Worksheet
 	 */
 	public function setBreak($pCell = 'A1', $pBreak = PHPExcel_Worksheet::BREAK_NONE)
@@ -1593,7 +1591,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 		if ($pCell != '') {
 			$this->_breaks[$pCell] = $pBreak;
 		} else {
-			throw new Exception('No cell coordinate specified.');
+			throw new PHPExcel_Exception('No cell coordinate specified.');
 		}
 
 		return $this;
@@ -1605,7 +1603,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
 	 * @param	integer	$pColumn	Numeric column coordinate of the cell
 	 * @param	integer	$pRow		Numeric row coordinate of the cell
 	 * @param	integer	$pBreak		Break type (type of PHPExcel_Worksheet::BREAK_*)
-	 * @throws	Exception
 	 * @return PHPExcel_Worksheet
 	 */
 	public function setBreakByColumnAndRow($pColumn = 0, $pRow = 1, $pBreak = PHPExcel_Worksheet::BREAK_NONE)
diff --git a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php
index df80aff..9bf3653 100644
--- a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php
+++ b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php
@@ -1029,7 +1029,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ
 						// End row
 						$objWriter->endElement();
 					}
-					$objWriter->flush();
+//					$objWriter->flush();
 				}
 
 			$objWriter->endElement();