Convert singleton calculation engine to multiton

This commit is contained in:
Mark Baker 2013-02-04 17:26:27 +00:00
parent 242f69bb29
commit 1e1a6ac361
3 changed files with 96 additions and 25 deletions

View File

@ -42,6 +42,13 @@ if (!defined('PHPEXCEL_ROOT')) {
*/ */
class PHPExcel class PHPExcel
{ {
/**
* Unique ID
*
* @var string
*/
private $_uniqueID;
/** /**
* Document properties * Document properties
* *
@ -63,6 +70,13 @@ class PHPExcel
*/ */
private $_workSheetCollection = array(); private $_workSheetCollection = array();
/**
* Calculation Engine
*
* @var PHPExcel_Calculation
*/
private $_calculationEngine = NULL;
/** /**
* Active sheet index * Active sheet index
* *
@ -103,6 +117,9 @@ class PHPExcel
*/ */
public function __construct() public function __construct()
{ {
$this->_uniqueID = uniqid();
$this->_calculationEngine = PHPExcel_Calculation::getInstance($this);
// Initialise worksheet collection and add one worksheet // Initialise worksheet collection and add one worksheet
$this->_workSheetCollection = array(); $this->_workSheetCollection = array();
$this->_workSheetCollection[] = new PHPExcel_Worksheet($this); $this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
@ -127,6 +144,14 @@ class PHPExcel
} }
/**
* Destroy this workbook
*/
public function __destruct() {
PHPExcel_Calculation::unsetInstance($this);
$this->disconnectWorksheets();
} // function __destruct()
/** /**
* Disconnect all worksheets from this PHPExcel workbook object, * Disconnect all worksheets from this PHPExcel workbook object,
* typically so that the PHPExcel object can be unset * typically so that the PHPExcel object can be unset
@ -141,6 +166,16 @@ class PHPExcel
$this->_workSheetCollection = array(); $this->_workSheetCollection = array();
} }
/**
* Return the calculation engine for this worksheet
*
* @return PHPExcel_Calculation
*/
public function getCalculationEngine() {
return $this->_calculationEngine;
} // function getCellCacheController()
/** /**
* Get properties * Get properties
* *
@ -824,12 +859,14 @@ class PHPExcel
foreach ($sheet->getColumnDimensions() as $columnDimension) { foreach ($sheet->getColumnDimensions() as $columnDimension) {
$columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] );
} }
}
// also do garbage collection for all the sheets // also do garbage collection for all the sheets
foreach ($this->getWorksheetIterator() as $sheet) {
$sheet->garbageCollect(); $sheet->garbageCollect();
} }
} }
public function getID() {
return $this->_uniqueID;
}
} }

View File

@ -96,13 +96,29 @@ class PHPExcel_Calculation {
private static $_instance; private static $_instance;
/**
* Instance of the workbook this Calculation Engine is using
*
* @access private
* @var PHPExcel
*/
private $_workbook;
/**
* List of instances of the calculation engine that we've instantiated
*
* @access private
* @var PHPExcel_Calculation[]
*/
private static $_workbookSets;
/** /**
* Calculation cache * Calculation cache
* *
* @access private * @access private
* @var array * @var array
*/ */
private static $_calculationCache = array (); private $_calculationCache = array ();
/** /**
@ -111,7 +127,7 @@ class PHPExcel_Calculation {
* @access private * @access private
* @var boolean * @var boolean
*/ */
private static $_calculationCacheEnabled = true; private $_calculationCacheEnabled = true;
/** /**
@ -1671,12 +1687,18 @@ class PHPExcel_Calculation {
private function __construct() { private function __construct(PHPExcel $workbook = NULL) {
$setPrecision = (PHP_INT_SIZE == 4) ? 12 : 16; $setPrecision = (PHP_INT_SIZE == 4) ? 12 : 16;
$this->_savedPrecision = ini_get('precision'); $this->_savedPrecision = ini_get('precision');
if ($this->_savedPrecision < $setPrecision) { if ($this->_savedPrecision < $setPrecision) {
ini_set('precision',$setPrecision); ini_set('precision',$setPrecision);
} }
if ($workbook !== NULL) {
self::$_workbookSets[$workbook->getID()] = $this;
}
$this->_workbook = $workbook;
} // function __construct() } // function __construct()
@ -1702,7 +1724,14 @@ class PHPExcel_Calculation {
* @access public * @access public
* @return PHPExcel_Calculation * @return PHPExcel_Calculation
*/ */
public static function getInstance() { public static function getInstance(PHPExcel $workbook = NULL) {
if ($workbook !== NULL) {
if (isset(self::$_workbookSets[$workbook->getID()])) {
return self::$_workbookSets[$workbook->getID()];
}
return new PHPExcel_Calculation($workbook);
}
if (!isset(self::$_instance) || (self::$_instance === NULL)) { if (!isset(self::$_instance) || (self::$_instance === NULL)) {
self::$_instance = new PHPExcel_Calculation(); self::$_instance = new PHPExcel_Calculation();
} }
@ -1710,6 +1739,13 @@ class PHPExcel_Calculation {
return self::$_instance; return self::$_instance;
} // function getInstance() } // function getInstance()
public static function unsetInstance(PHPExcel $workbook = NULL) {
if ($workbook !== NULL) {
if (isset(self::$_workbookSets[$workbook->getID()])) {
unset(self::$_workbookSets[$workbook->getID()]);
}
}
}
/** /**
* Flush the calculation cache for any existing instance of this class * Flush the calculation cache for any existing instance of this class
@ -1718,10 +1754,8 @@ class PHPExcel_Calculation {
* @access public * @access public
* @return null * @return null
*/ */
public static function flushInstance() { public function flushInstance() {
if (isset(self::$_instance) && (self::$_instance !== NULL)) { $this->clearCalculationCache();
self::$_instance->clearCalculationCache();
}
} // function flushInstance() } // function flushInstance()
@ -1792,7 +1826,7 @@ class PHPExcel_Calculation {
* @return boolean * @return boolean
*/ */
public function getCalculationCacheEnabled() { public function getCalculationCacheEnabled() {
return self::$_calculationCacheEnabled; return $this->_calculationCacheEnabled;
} // function getCalculationCacheEnabled() } // function getCalculationCacheEnabled()
@ -1803,7 +1837,7 @@ class PHPExcel_Calculation {
* @param boolean $pValue * @param boolean $pValue
*/ */
public function setCalculationCacheEnabled($pValue = true) { public function setCalculationCacheEnabled($pValue = true) {
self::$_calculationCacheEnabled = $pValue; $this->_calculationCacheEnabled = $pValue;
$this->clearCalculationCache(); $this->clearCalculationCache();
} // function setCalculationCacheEnabled() } // function setCalculationCacheEnabled()
@ -1828,7 +1862,7 @@ class PHPExcel_Calculation {
* Clear calculation cache * Clear calculation cache
*/ */
public function clearCalculationCache() { public function clearCalculationCache() {
self::$_calculationCache = array(); $this->_calculationCache = array();
} // function clearCalculationCache() } // function clearCalculationCache()
@ -2206,7 +2240,7 @@ class PHPExcel_Calculation {
// Disable calculation cacheing because it only applies to cell calculations, not straight formulae // Disable calculation cacheing because it only applies to cell calculations, not straight formulae
// But don't actually flush any cache // But don't actually flush any cache
$resetCache = $this->getCalculationCacheEnabled(); $resetCache = $this->getCalculationCacheEnabled();
self::$_calculationCacheEnabled = false; $this->_calculationCacheEnabled = FALSE;
// Execute the calculation // Execute the calculation
try { try {
$result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
@ -2215,7 +2249,7 @@ class PHPExcel_Calculation {
} }
// Reset calculation cacheing to its previous state // Reset calculation cacheing to its previous state
self::$_calculationCacheEnabled = $resetCache; $this->_calculationCacheEnabled = $resetCache;
return $result; return $result;
} // function calculateFormula() } // function calculateFormula()
@ -2250,15 +2284,15 @@ class PHPExcel_Calculation {
} }
// Is calculation cacheing enabled? // Is calculation cacheing enabled?
if ($cellID !== NULL) { if ($cellID !== NULL) {
if (self::$_calculationCacheEnabled) { if ($this->_calculationCacheEnabled) {
// Is the value present in calculation cache? // Is the value present in calculation cache?
$this->_writeDebug('Testing cache value for cell ', $cellID); $this->_writeDebug('Testing cache value for cell ', $cellID);
// echo 'Testing cache value<br />'; // echo 'Testing cache value<br />';
if (isset(self::$_calculationCache[$wsTitle][$cellID])) { if (isset($this->_calculationCache[$wsTitle][$cellID])) {
// echo 'Value is in cache<br />'; // echo 'Value is in cache<br />';
$this->_writeDebug('Retrieving value for ', $cellID, ' from cache'); $this->_writeDebug('Retrieving value for ', $cellID, ' from cache');
// Return the cached result // Return the cached result
$returnValue = self::$_calculationCache[$wsTitle][$cellID]; $returnValue = $this->_calculationCache[$wsTitle][$cellID];
// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache<br />'; // echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache<br />';
if (is_array($returnValue)) { if (is_array($returnValue)) {
$returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue); $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue);
@ -2294,8 +2328,8 @@ class PHPExcel_Calculation {
// Save to calculation cache // Save to calculation cache
if ($cellID !== NULL) { if ($cellID !== NULL) {
if (self::$_calculationCacheEnabled) { if ($this->_calculationCacheEnabled) {
self::$_calculationCache[$wsTitle][$cellID] = $cellValue; $this->_calculationCache[$wsTitle][$cellID] = $cellValue;
} }
} }

View File

@ -288,7 +288,7 @@ class PHPExcel_Cell
if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) { if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) {
try { try {
// echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value<br />'; // echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value<br />';
$result = PHPExcel_Calculation::getInstance()->calculateCellValue($this,$resetLog); $result = $this->getParent()->getParent()->getCalculationEngine()->calculateCellValue($this,$resetLog);
// echo $this->getCoordinate().' calculation result is '.$result.'<br />'; // echo $this->getCoordinate().' calculation result is '.$result.'<br />';
} catch ( PHPExcel_Exception $ex ) { } catch ( PHPExcel_Exception $ex ) {
if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) { if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) {
@ -859,11 +859,11 @@ class PHPExcel_Cell
*/ */
public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b) public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b)
{ {
if ($a->_row < $b->_row) { if ($a->getRow() < $b->getRow()) {
return -1; return -1;
} elseif ($a->_row > $b->_row) { } elseif ($a->getRow() > $b->getRow()) {
return 1; return 1;
} elseif (self::columnIndexFromString($a->_column) < self::columnIndexFromString($b->_column)) { } elseif (self::columnIndexFromString($a->getColumn()) < self::columnIndexFromString($b->getColumn())) {
return -1; return -1;
} else { } else {
return 1; return 1;