diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php
index 2a450c4c..19213c24 100644
--- a/Classes/PHPExcel.php
+++ b/Classes/PHPExcel.php
@@ -42,6 +42,13 @@ if (!defined('PHPEXCEL_ROOT')) {
*/
class PHPExcel
{
+ /**
+ * Unique ID
+ *
+ * @var string
+ */
+ private $_uniqueID;
+
/**
* Document properties
*
@@ -63,6 +70,13 @@ class PHPExcel
*/
private $_workSheetCollection = array();
+ /**
+ * Calculation Engine
+ *
+ * @var PHPExcel_Calculation
+ */
+ private $_calculationEngine = NULL;
+
/**
* Active sheet index
*
@@ -103,6 +117,9 @@ class PHPExcel
*/
public function __construct()
{
+ $this->_uniqueID = uniqid();
+ $this->_calculationEngine = PHPExcel_Calculation::getInstance($this);
+
// Initialise worksheet collection and add one worksheet
$this->_workSheetCollection = array();
$this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
@@ -126,13 +143,22 @@ class PHPExcel
$this->addCellStyleXf(new PHPExcel_Style);
}
+ /**
+ * Code to execute when this worksheet is unset()
+ *
+ */
+ public function __destruct() {
+ PHPExcel_Calculation::unsetInstance($this);
+ $this->disconnectWorksheets();
+ } // function __destruct()
/**
* Disconnect all worksheets from this PHPExcel workbook object,
* typically so that the PHPExcel object can be unset
*
*/
- public function disconnectWorksheets() {
+ public function disconnectWorksheets()
+ {
$worksheet = NULL;
foreach($this->_workSheetCollection as $k => &$worksheet) {
$worksheet->disconnectCells();
@@ -142,13 +168,15 @@ class PHPExcel
$this->_workSheetCollection = array();
}
- /**
- * Code to execute when this worksheet is unset()
- *
- */
- function __destruct() {
- $this->disconnectWorksheets();
- }
+ /**
+ * Return the calculation engine for this worksheet
+ *
+ * @return PHPExcel_Calculation
+ */
+ public function getCalculationEngine()
+ {
+ return $this->_calculationEngine;
+ } // function getCellCacheController()
/**
* Get properties
@@ -849,12 +877,14 @@ class PHPExcel
foreach ($sheet->getColumnDimensions() as $columnDimension) {
$columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] );
}
- }
- // also do garbage collection for all the sheets
- foreach ($this->getWorksheetIterator() as $sheet) {
+ // also do garbage collection for all the sheets
$sheet->garbageCollect();
}
}
+ public function getID() {
+ return $this->_uniqueID;
+ }
+
}
diff --git a/Classes/PHPExcel/CachedObjectStorage/APC.php b/Classes/PHPExcel/CachedObjectStorage/APC.php
index 8f1e931e..2e61f03b 100644
--- a/Classes/PHPExcel/CachedObjectStorage/APC.php
+++ b/Classes/PHPExcel/CachedObjectStorage/APC.php
@@ -154,8 +154,8 @@ class PHPExcel_CachedObjectStorage_APC extends PHPExcel_CachedObjectStorage_Cach
// Set current entry to the requested entry
$this->_currentObjectID = $pCoord;
$this->_currentObject = unserialize($obj);
- // Re-attach the parent worksheet
- $this->_currentObject->attach($this->_parent);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php
index 924b4b44..6dd6c1a5 100644
--- a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php
+++ b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php
@@ -86,6 +86,11 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase {
} // function __construct()
+ public function getParent()
+ {
+ return $this->_parent;
+ }
+
/**
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
*
@@ -101,6 +106,27 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase {
} // function isDataSet()
+ /**
+ * Move a cell object from one address to another
+ *
+ * @param string $fromAddress Current address of the cell to move
+ * @param string $toAddress Destination address of the cell to move
+ * @return boolean
+ */
+ public function moveCell($fromAddress, $toAddress) {
+ if ($fromAddress === $this->_currentObjectID) {
+ $this->_currentObjectID = $toAddress;
+ }
+ $this->_currentCellIsDirty = true;
+ if (isset($this->_cellCache[$fromAddress])) {
+ $this->_cellCache[$toAddress] = &$this->_cellCache[$fromAddress];
+ unset($this->_cellCache[$fromAddress]);
+ }
+
+ return TRUE;
+ } // function moveCell()
+
+
/**
* Add or Update a cell in cache
*
@@ -188,6 +214,23 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase {
}
+ public function getCurrentAddress()
+ {
+ return $this->_currentObjectID;
+ }
+
+ public function getCurrentColumn()
+ {
+ list($column,$row) = sscanf($this->_currentObjectID, '%[A-Z]%d');
+ return $column;
+ }
+
+ public function getCurrentRow()
+ {
+ list($column,$row) = sscanf($this->_currentObjectID, '%[A-Z]%d');
+ return $row;
+ }
+
/**
* Get highest worksheet column
*
@@ -237,7 +280,7 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase {
$this->_parent = $parent;
if (($this->_currentObject !== NULL) && (is_object($this->_currentObject))) {
- $this->_currentObject->attach($parent);
+ $this->_currentObject->attach($this);
}
} // function copyCellCollection()
diff --git a/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php b/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php
index 3fde3851..956fd56e 100644
--- a/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php
+++ b/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php
@@ -124,8 +124,8 @@ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage
$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);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/Igbinary.php b/Classes/PHPExcel/CachedObjectStorage/Igbinary.php
index 6e33468a..7e7d1dfc 100644
--- a/Classes/PHPExcel/CachedObjectStorage/Igbinary.php
+++ b/Classes/PHPExcel/CachedObjectStorage/Igbinary.php
@@ -96,8 +96,8 @@ class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage
// Set current entry to the requested entry
$this->_currentObjectID = $pCoord;
$this->_currentObject = igbinary_unserialize($this->_cellCache[$pCoord]);
- // Re-attach the parent worksheet
- $this->_currentObject->attach($this->_parent);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/Memcache.php b/Classes/PHPExcel/CachedObjectStorage/Memcache.php
index 76ff9096..a5440599 100644
--- a/Classes/PHPExcel/CachedObjectStorage/Memcache.php
+++ b/Classes/PHPExcel/CachedObjectStorage/Memcache.php
@@ -158,8 +158,8 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage
// Set current entry to the requested entry
$this->_currentObjectID = $pCoord;
$this->_currentObject = unserialize($obj);
- // Re-attach the parent worksheet
- $this->_currentObject->attach($this->_parent);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/Memory.php b/Classes/PHPExcel/CachedObjectStorage/Memory.php
index 416b1e47..1e05b062 100644
--- a/Classes/PHPExcel/CachedObjectStorage/Memory.php
+++ b/Classes/PHPExcel/CachedObjectStorage/Memory.php
@@ -48,11 +48,15 @@ class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_C
*
* @param string $pCoord Coordinate address of the cell to update
* @param PHPExcel_Cell $cell Cell to update
- * @return void
+ * @return PHPExcel_Cell
* @throws PHPExcel_Exception
*/
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
$this->_cellCache[$pCoord] = $cell;
+
+ // Set current entry to the new/updated entry
+ $this->_currentObjectID = $pCoord;
+
return $cell;
} // function addCacheData()
@@ -67,10 +71,14 @@ class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_C
public function getCacheData($pCoord) {
// Check if the entry that has been requested actually exists
if (!isset($this->_cellCache[$pCoord])) {
+ $this->_currentObjectID = NULL;
// Return null if requested entry doesn't exist in cache
return null;
}
+ // Set current entry to the requested entry
+ $this->_currentObjectID = $pCoord;
+
// Return requested entry
return $this->_cellCache[$pCoord];
} // function getCacheData()
diff --git a/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php b/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php
index ecb29b8c..43ed104f 100644
--- a/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php
+++ b/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php
@@ -96,8 +96,8 @@ class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStora
// 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);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php b/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php
index 3feb5faf..5e1f8381 100644
--- a/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php
+++ b/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php
@@ -96,8 +96,8 @@ class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjec
// 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);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php b/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php
index e6eafb7f..5b13e668 100644
--- a/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php
+++ b/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php
@@ -116,8 +116,8 @@ class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_
$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);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite.php b/Classes/PHPExcel/CachedObjectStorage/SQLite.php
index 915d21d0..5e82c089 100644
--- a/Classes/PHPExcel/CachedObjectStorage/SQLite.php
+++ b/Classes/PHPExcel/CachedObjectStorage/SQLite.php
@@ -116,8 +116,8 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C
$cellResult = $cellResultSet->fetchSingle();
$this->_currentObject = unserialize($cellResult);
- // Re-attach the parent worksheet
- $this->_currentObject->attach($this->_parent);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
@@ -169,6 +169,32 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C
} // function deleteCacheData()
+ /**
+ * Move a cell object from one address to another
+ *
+ * @param string $fromAddress Current address of the cell to move
+ * @param string $toAddress Destination address of the cell to move
+ * @return boolean
+ */
+ public function moveCell($fromAddress, $toAddress) {
+ if ($fromAddress === $this->_currentObjectID) {
+ $this->_currentObjectID = $toAddress;
+ }
+
+ $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$toAddress."'";
+ $result = $this->_DBHandle->exec($query);
+ if ($result === false)
+ throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
+
+ $query = "UPDATE kvp_".$this->_TableName." SET id='".$toAddress."' WHERE id='".$fromAddress."'";
+ $result = $this->_DBHandle->exec($query);
+ if ($result === false)
+ throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
+
+ return TRUE;
+ } // function moveCell()
+
+
/**
* Get a list of all cell addresses currently held in cache
*
@@ -256,6 +282,10 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C
* Destroy this cell collection
*/
public function __destruct() {
+ if (!is_null($this->_DBHandle)) {
+ $this->_DBHandle->queryExec('DROP TABLE kvp_'.$this->_TableName);
+ $this->_DBHandle->close();
+ }
$this->_DBHandle = null;
} // function __destruct()
diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php
index f9ca246e..ecd80294 100644
--- a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php
+++ b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php
@@ -49,6 +49,11 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
*/
private $_DBHandle = null;
+ private $_selectQuery;
+ private $_insertQuery;
+ private $_updateQuery;
+ private $_deleteQuery;
+
/**
* Store cell data in cache for the current cell object if it's "dirty",
* and the 'nullify' the current cell object
@@ -60,10 +65,9 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
if ($this->_currentCellIsDirty) {
$this->_currentObject->detach();
- $query = $this->_DBHandle->prepare("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES(:id,:data)");
- $query->bindValue('id',$this->_currentObjectID,SQLITE3_TEXT);
- $query->bindValue('data',serialize($this->_currentObject),SQLITE3_BLOB);
- $result = $query->execute();
+ $this->_insertQuery->bindValue('id',$this->_currentObjectID,SQLITE3_TEXT);
+ $this->_insertQuery->bindValue('data',serialize($this->_currentObject),SQLITE3_BLOB);
+ $result = $this->_insertQuery->execute();
if ($result === false)
throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
$this->_currentCellIsDirty = false;
@@ -106,21 +110,23 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
}
$this->_storeData();
- $query = "SELECT value FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'";
- $cellResult = $this->_DBHandle->querySingle($query);
- if ($cellResult === false) {
+ $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT);
+ $cellResult = $this->_selectQuery->execute();
+ if ($cellResult === FALSE) {
throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
- } elseif (is_null($cellResult)) {
+ }
+ $cellData = $cellResult->fetchArray(SQLITE3_ASSOC);
+ if ($cellData === FALSE) {
// Return null if requested entry doesn't exist in cache
- return null;
+ return NULL;
}
// Set current entry to the requested entry
$this->_currentObjectID = $pCoord;
- $this->_currentObject = unserialize($cellResult);
- // Re-attach the parent worksheet
- $this->_currentObject->attach($this->_parent);
+ $this->_currentObject = unserialize($cellData['value']);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
@@ -135,19 +141,18 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
*/
public function isDataSet($pCoord) {
if ($pCoord === $this->_currentObjectID) {
- return true;
+ return TRUE;
}
// Check if the requested entry exists in the cache
- $query = "SELECT id FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'";
- $cellResult = $this->_DBHandle->querySingle($query);
- if ($cellResult === false) {
+ $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT);
+ $cellResult = $this->_selectQuery->execute();
+ if ($cellResult === FALSE) {
throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
- } elseif (is_null($cellResult)) {
- // Return null if requested entry doesn't exist in cache
- return false;
}
- return true;
+ $cellData = $cellResult->fetchArray(SQLITE3_ASSOC);
+
+ return ($cellData === FALSE) ? FALSE : TRUE;
} // function isDataSet()
@@ -160,17 +165,44 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
public function deleteCacheData($pCoord) {
if ($pCoord === $this->_currentObjectID) {
$this->_currentObject->detach();
- $this->_currentObjectID = $this->_currentObject = null;
+ $this->_currentObjectID = $this->_currentObject = NULL;
}
// Check if the requested entry exists in the cache
- $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'";
- $result = $this->_DBHandle->exec($query);
+ $this->_deleteQuery->bindValue('id',$pCoord,SQLITE3_TEXT);
+ $result = $this->_deleteQuery->execute();
+ if ($result === FALSE)
+ throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
+
+ $this->_currentCellIsDirty = FALSE;
+ } // function deleteCacheData()
+
+
+ /**
+ * Move a cell object from one address to another
+ *
+ * @param string $fromAddress Current address of the cell to move
+ * @param string $toAddress Destination address of the cell to move
+ * @return boolean
+ */
+ public function moveCell($fromAddress, $toAddress) {
+ if ($fromAddress === $this->_currentObjectID) {
+ $this->_currentObjectID = $toAddress;
+ }
+
+ $this->_deleteQuery->bindValue('id',$toAddress,SQLITE3_TEXT);
+ $result = $this->_deleteQuery->execute();
if ($result === false)
throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
- $this->_currentCellIsDirty = false;
- } // function deleteCacheData()
+ $this->_updateQuery->bindValue('toid',$toAddress,SQLITE3_TEXT);
+ $this->_updateQuery->bindValue('fromid',$fromAddress,SQLITE3_TEXT);
+ $result = $this->_updateQuery->execute();
+ if ($result === false)
+ throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
+
+ return TRUE;
+ } // function moveCell()
/**
@@ -253,6 +285,11 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
if (!$this->_DBHandle->exec('CREATE TABLE kvp_'.$this->_TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)'))
throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg());
}
+
+ $this->_selectQuery = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id");
+ $this->_insertQuery = $this->_DBHandle->prepare("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES(:id,:data)");
+ $this->_updateQuery = $this->_DBHandle->prepare("UPDATE kvp_".$this->_TableName." SET id=:toId WHERE id=:fromId");
+ $this->_deleteQuery = $this->_DBHandle->prepare("DELETE FROM kvp_".$this->_TableName." WHERE id = :id");
} // function __construct()
@@ -261,6 +298,7 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_
*/
public function __destruct() {
if (!is_null($this->_DBHandle)) {
+ $this->_DBHandle->exec('DROP TABLE kvp_'.$this->_TableName);
$this->_DBHandle->close();
}
$this->_DBHandle = null;
diff --git a/Classes/PHPExcel/CachedObjectStorage/Wincache.php b/Classes/PHPExcel/CachedObjectStorage/Wincache.php
index 38d61166..97b16397 100644
--- a/Classes/PHPExcel/CachedObjectStorage/Wincache.php
+++ b/Classes/PHPExcel/CachedObjectStorage/Wincache.php
@@ -158,8 +158,8 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage
// Set current entry to the requested entry
$this->_currentObjectID = $pCoord;
$this->_currentObject = unserialize($obj);
- // Re-attach the parent worksheet
- $this->_currentObject->attach($this->_parent);
+ // Re-attach this as the cell's parent
+ $this->_currentObject->attach($this);
// Return requested entry
return $this->_currentObject;
diff --git a/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php b/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php
new file mode 100644
index 00000000..e64b4686
--- /dev/null
+++ b/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php
@@ -0,0 +1,58 @@
+_stack);
+ }
+
+ public function push($value) {
+ $this->_stack[] = $value;
+ } // function push()
+
+ public function pop() {
+ return array_pop($this->_stack);
+ } // function pop()
+
+ public function onStack($value) {
+ return in_array($value,$this->_stack);
+ }
+
+ public function clear() {
+ $this->_stack = array();
+ } // function push()
+
+ public function showStack() {
+ return $this->_stack;
+ }
+
+} // class PHPExcel_CalcEngine_CyclicReferenceStack
diff --git a/Classes/PHPExcel/CalcEngine/Logger.php b/Classes/PHPExcel/CalcEngine/Logger.php
new file mode 100644
index 00000000..250f841d
--- /dev/null
+++ b/Classes/PHPExcel/CalcEngine/Logger.php
@@ -0,0 +1,121 @@
+_cellStack = $stack;
+ }
+
+ public function setWriteDebugLog($pValue = FALSE) {
+ $this->_writeDebugLog = $pValue;
+ }
+
+ public function getWriteDebugLog() {
+ return $this->_writeDebugLog;
+ }
+
+ public function setEchoDebugLog($pValue = FALSE) {
+ $this->_echoDebugLog = $pValue;
+ }
+
+ public function getEchoDebugLog() {
+ return $this->_echoDebugLog;
+ }
+
+ public function writeDebugLog() {
+ // Only write the debug log if logging is enabled
+ if ($this->_writeDebugLog) {
+ $message = implode(func_get_args());
+ $cellReference = implode(' -> ', $this->_cellStack->showStack());
+ if ($this->_echoDebugLog) {
+ echo $cellReference,
+ ($this->_cellStack->count() > 0 ? ' => ' : ''),
+ $message,
+ PHP_EOL;
+ }
+ $this->_debugLog[] = $cellReference .
+ ($this->_cellStack->count() > 0 ? ' => ' : '') .
+ $message;
+ }
+ } // function _writeDebug()
+
+ public function clearLog() {
+ $this->_debugLog = array();
+ } // function flushLogger()
+
+ public function getLog() {
+ return $this->_debugLog;
+ } // function flushLogger()
+
+} // class PHPExcel_CalcEngine_Logger
+
diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php
index 254a4e9c..c98e50cb 100644
--- a/Classes/PHPExcel/Calculation.php
+++ b/Classes/PHPExcel/Calculation.php
@@ -96,13 +96,29 @@ class PHPExcel_Calculation {
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
*
* @access private
* @var array
*/
- private static $_calculationCache = array ();
+ private $_calculationCache = array ();
/**
@@ -111,7 +127,7 @@ class PHPExcel_Calculation {
* @access private
* @var boolean
*/
- private static $_calculationCacheEnabled = true;
+ private $_calculationCacheEnabled = TRUE;
/**
@@ -121,10 +137,10 @@ class PHPExcel_Calculation {
* @access private
* @var array
*/
- private static $_operators = array('+' => true, '-' => true, '*' => true, '/' => true,
- '^' => true, '&' => true, '%' => false, '~' => false,
- '>' => true, '<' => true, '=' => true, '>=' => true,
- '<=' => true, '<>' => true, '|' => true, ':' => true
+ private static $_operators = array('+' => TRUE, '-' => TRUE, '*' => TRUE, '/' => TRUE,
+ '^' => TRUE, '&' => TRUE, '%' => FALSE, '~' => FALSE,
+ '>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE,
+ '<=' => TRUE, '<>' => TRUE, '|' => TRUE, ':' => TRUE
);
@@ -134,12 +150,21 @@ class PHPExcel_Calculation {
* @access private
* @var array
*/
- private static $_binaryOperators = array('+' => true, '-' => true, '*' => true, '/' => true,
- '^' => true, '&' => true, '>' => true, '<' => true,
- '=' => true, '>=' => true, '<=' => true, '<>' => true,
- '|' => true, ':' => true
+ private static $_binaryOperators = array('+' => TRUE, '-' => TRUE, '*' => TRUE, '/' => TRUE,
+ '^' => TRUE, '&' => TRUE, '>' => TRUE, '<' => TRUE,
+ '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE,
+ '|' => TRUE, ':' => TRUE
);
+ /**
+ * The debug log generated by the calculation engine
+ *
+ * @access private
+ * @var PHPExcel_CalcEngine_Logger
+ *
+ */
+ private $debugLog;
+
/**
* Flag to determine how formula errors should be handled
* If true, then a user error will be triggered
@@ -149,7 +174,7 @@ class PHPExcel_Calculation {
* @var boolean
*
*/
- public $suppressFormulaErrors = false;
+ public $suppressFormulaErrors = FALSE;
/**
* Error message for any error that was raised/thrown by the calculation engine
@@ -158,31 +183,7 @@ class PHPExcel_Calculation {
* @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;
-
- /**
- * Flag to determine whether a debug log should be echoed by the calculation engine
- * If true, then a debug log will be echoed
- * If false, then a debug log will not be echoed
- * A debug log can only be echoed if it is generated
- *
- * @access public
- * @var boolean
- *
- */
- public $echoDebugLog = false;
-
+ public $formulaError = NULL;
/**
* An array of the nested cell references accessed by the calculation engine, used for the debug log
@@ -191,22 +192,14 @@ class PHPExcel_Calculation {
* @var array of string
*
*/
- private $debugLogStack = array();
+ private $_cyclicReferenceStack;
- /**
- * 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 $_savedPrecision = 12;
+ private $_savedPrecision = 14;
private static $_localeLanguage = 'en_us'; // US English (default locale)
@@ -221,9 +214,9 @@ class PHPExcel_Calculation {
// Constant conversion from text name/value to actual (datatyped) value
- private static $_ExcelConstants = array('TRUE' => true,
- 'FALSE' => false,
- 'NULL' => null
+ private static $_ExcelConstants = array('TRUE' => TRUE,
+ 'FALSE' => FALSE,
+ 'NULL' => NULL
);
// PHPExcel functions
@@ -395,7 +388,7 @@ class PHPExcel_Calculation {
'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMN',
'argumentCount' => '-1',
- 'passByReference' => array(true)
+ 'passByReference' => array(TRUE)
),
'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMNS',
@@ -804,7 +797,7 @@ class PHPExcel_Calculation {
'HYPERLINK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::HYPERLINK',
'argumentCount' => '1,2',
- 'passCellReference'=> true
+ 'passCellReference'=> TRUE
),
'HYPGEOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL,
'functionCall' => 'PHPExcel_Calculation_Statistical::HYPGEOMDIST',
@@ -893,7 +886,7 @@ class PHPExcel_Calculation {
'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::INDIRECT',
'argumentCount' => '1,2',
- 'passCellReference'=> true
+ 'passCellReference'=> TRUE
),
'INFO' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION,
'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY',
@@ -1210,8 +1203,8 @@ class PHPExcel_Calculation {
'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::OFFSET',
'argumentCount' => '3,5',
- 'passCellReference'=> true,
- 'passByReference' => array(true)
+ 'passCellReference'=> TRUE,
+ 'passByReference' => array(TRUE)
),
'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL,
'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_OR',
@@ -1356,7 +1349,7 @@ class PHPExcel_Calculation {
'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::ROW',
'argumentCount' => '-1',
- 'passByReference' => array(true)
+ 'passByReference' => array(TRUE)
),
'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => 'PHPExcel_Calculation_LookupRef::ROWS',
@@ -1671,12 +1664,20 @@ class PHPExcel_Calculation {
- private function __construct() {
- $setPrecision = (PHP_INT_SIZE == 4) ? 12 : 16;
+ private function __construct(PHPExcel $workbook = NULL) {
+ $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16;
$this->_savedPrecision = ini_get('precision');
if ($this->_savedPrecision < $setPrecision) {
ini_set('precision',$setPrecision);
}
+
+ if ($workbook !== NULL) {
+ self::$_workbookSets[$workbook->getID()] = $this;
+ }
+
+ $this->_workbook = $workbook;
+ $this->_cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack();
+ $this->_debugLog = new PHPExcel_CalcEngine_Logger($this->_cyclicReferenceStack);
} // function __construct()
@@ -1702,7 +1703,14 @@ class PHPExcel_Calculation {
* @access public
* @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)) {
self::$_instance = new PHPExcel_Calculation();
}
@@ -1710,6 +1718,13 @@ class PHPExcel_Calculation {
return self::$_instance;
} // 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
@@ -1718,13 +1733,15 @@ class PHPExcel_Calculation {
* @access public
* @return null
*/
- public static function flushInstance() {
- if (isset(self::$_instance) && (self::$_instance !== NULL)) {
- self::$_instance->clearCalculationCache();
- }
+ public function flushInstance() {
+ $this->clearCalculationCache();
} // function flushInstance()
+ public function getDebugLog() {
+ return $this->_debugLog;
+ }
+
/**
* __clone implementation. Cloning should not be allowed in a Singleton!
*
@@ -1732,7 +1749,7 @@ class PHPExcel_Calculation {
* @throws PHPExcel_Calculation_Exception
*/
public final function __clone() {
- throw new PHPExcel_Calculation_Exception ('Cloning a Singleton is not allowed!');
+ throw new PHPExcel_Calculation_Exception ('Cloning the calculation engine is not allowed!');
} // function __clone()
@@ -1768,10 +1785,10 @@ class PHPExcel_Calculation {
($returnType == self::RETURN_ARRAY_AS_ERROR) ||
($returnType == self::RETURN_ARRAY_AS_ARRAY)) {
self::$returnArrayAsType = $returnType;
- return true;
+ return TRUE;
}
- return false;
- } // function setExcelCalendar()
+ return FALSE;
+ } // function setArrayReturnType()
/**
@@ -1782,7 +1799,7 @@ class PHPExcel_Calculation {
*/
public static function getArrayReturnType() {
return self::$returnArrayAsType;
- } // function getExcelCalendar()
+ } // function getArrayReturnType()
/**
@@ -1792,18 +1809,17 @@ class PHPExcel_Calculation {
* @return boolean
*/
public function getCalculationCacheEnabled() {
- return self::$_calculationCacheEnabled;
+ return $this->_calculationCacheEnabled;
} // function getCalculationCacheEnabled()
-
/**
* Enable/disable calculation cache
*
* @access public
* @param boolean $pValue
*/
- public function setCalculationCacheEnabled($pValue = true) {
- self::$_calculationCacheEnabled = $pValue;
+ public function setCalculationCacheEnabled($pValue = TRUE) {
+ $this->_calculationCacheEnabled = $pValue;
$this->clearCalculationCache();
} // function setCalculationCacheEnabled()
@@ -1812,7 +1828,7 @@ class PHPExcel_Calculation {
* Enable calculation cache
*/
public function enableCalculationCache() {
- $this->setCalculationCacheEnabled(true);
+ $this->setCalculationCacheEnabled(TRUE);
} // function enableCalculationCache()
@@ -1820,7 +1836,7 @@ class PHPExcel_Calculation {
* Disable calculation cache
*/
public function disableCalculationCache() {
- $this->setCalculationCacheEnabled(false);
+ $this->setCalculationCacheEnabled(FALSE);
} // function disableCalculationCache()
@@ -1828,9 +1844,28 @@ class PHPExcel_Calculation {
* Clear calculation cache
*/
public function clearCalculationCache() {
- self::$_calculationCache = array();
+ $this->_calculationCache = array();
} // function clearCalculationCache()
+ /**
+ * Clear calculation cache for a specified worksheet
+ */
+ public function clearCalculationCacheForWorksheet($worksheetName) {
+ if (isset($this->_calculationCache[$worksheetName])) {
+ unset($this->_calculationCache[$worksheetName]);
+ }
+ } // function clearCalculationCacheForWorksheet()
+
+ /**
+ * Rename calculation cache for a specified worksheet
+ */
+ public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName) {
+ if (isset($this->_calculationCache[$fromWorksheetName])) {
+ $this->_calculationCache[$toWorksheetName] = &$this->_calculationCache[$fromWorksheetName];
+ unset($this->_calculationCache[$fromWorksheetName]);
+ }
+ } // function renameCalculationCacheForWorksheet()
+
/**
* Get the currently defined locale code
@@ -1850,7 +1885,7 @@ class PHPExcel_Calculation {
public function setLocale($locale='en_us') {
// Identify our locale and language
$language = $locale = strtolower($locale);
- if (strpos($locale,'_') !== false) {
+ if (strpos($locale,'_') !== FALSE) {
list($language) = explode('_',$locale);
}
@@ -1871,14 +1906,14 @@ class PHPExcel_Calculation {
// If there isn't a locale specific function file, look for a language specific function file
$functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'functions';
if (!file_exists($functionNamesFile)) {
- return false;
+ 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) {
+ if (strpos($localeFunction,'=') !== FALSE) {
list($fName,$lfName) = explode('=',$localeFunction);
$fName = trim($fName);
$lfName = trim($lfName);
@@ -1899,7 +1934,7 @@ class PHPExcel_Calculation {
$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) {
+ if (strpos($localeSetting,'=') !== FALSE) {
list($settingName,$settingValue) = explode('=',$localeSetting);
$settingName = strtoupper(trim($settingName));
switch ($settingName) {
@@ -1913,11 +1948,11 @@ class PHPExcel_Calculation {
}
self::$functionReplaceFromExcel = self::$functionReplaceToExcel =
- self::$functionReplaceFromLocale = self::$functionReplaceToLocale = null;
+ self::$functionReplaceFromLocale = self::$functionReplaceToLocale = NULL;
self::$_localeLanguage = $locale;
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
} // function setLocale()
@@ -1927,9 +1962,9 @@ class PHPExcel_Calculation {
for ($i = 0; $i < $strlen; ++$i) {
$chr = mb_substr($formula,$i,1);
switch ($chr) {
- case '{' : $inBraces = true;
+ case '{' : $inBraces = TRUE;
break;
- case '}' : $inBraces = false;
+ case '}' : $inBraces = FALSE;
break;
case $fromSeparator :
if (!$inBraces) {
@@ -1943,13 +1978,13 @@ class PHPExcel_Calculation {
private static function _translateFormula($from,$to,$formula,$fromSeparator,$toSeparator) {
// Convert any Excel function names to the required language
if (self::$_localeLanguage !== 'en_us') {
- $inBraces = false;
+ $inBraces = FALSE;
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
- if (strpos($formula,'"') !== false) {
+ 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 = false;
+ $i = FALSE;
foreach($temp as &$value) {
// Only count/replace in alternating array entries
if ($i = !$i) {
@@ -1970,8 +2005,8 @@ class PHPExcel_Calculation {
return $formula;
}
- private static $functionReplaceFromExcel = null;
- private static $functionReplaceToLocale = null;
+ private static $functionReplaceFromExcel = NULL;
+ private static $functionReplaceToLocale = NULL;
public function _translateFormulaToLocale($formula) {
if (self::$functionReplaceFromExcel === NULL) {
@@ -1999,8 +2034,8 @@ class PHPExcel_Calculation {
} // function _translateFormulaToLocale()
- private static $functionReplaceFromLocale = null;
- private static $functionReplaceToExcel = null;
+ private static $functionReplaceFromLocale = NULL;
+ private static $functionReplaceToExcel = NULL;
public function _translateFormulaToEnglish($formula) {
if (self::$functionReplaceFromLocale === NULL) {
@@ -2096,7 +2131,7 @@ class PHPExcel_Calculation {
* @return mixed
* @throws PHPExcel_Calculation_Exception
*/
- public function calculate(PHPExcel_Cell $pCell = null) {
+ public function calculate(PHPExcel_Cell $pCell = NULL) {
try {
return $this->calculateCellValue($pCell);
} catch (PHPExcel_Exception $e) {
@@ -2114,25 +2149,22 @@ class PHPExcel_Calculation {
* @return mixed
* @throws PHPExcel_Calculation_Exception
*/
- public function calculateCellValue(PHPExcel_Cell $pCell = null, $resetLog = true) {
- if ($resetLog) {
- // 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;
- }
-
- // Read the formula from the cell
+ public function calculateCellValue(PHPExcel_Cell $pCell = NULL, $resetLog = TRUE) {
if ($pCell === NULL) {
return NULL;
}
+ $returnArrayAsType = self::$returnArrayAsType;
if ($resetLog) {
- self::$returnArrayAsType = $returnArrayAsType;
+ // Initialise the logging settings if requested
+ $this->formulaError = null;
+ $this->_debugLog->clearLog();
+ $this->_cyclicReferenceStack->clear();
+ $this->_cyclicFormulaCount = 1;
+
+ self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY;
}
+
// Execute the calculation for the cell formula
try {
$result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell));
@@ -2141,6 +2173,7 @@ class PHPExcel_Calculation {
}
if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) {
+ self::$returnArrayAsType = $returnArrayAsType;
$testResult = PHPExcel_Calculation_Functions::flattenArray($result);
if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) {
return PHPExcel_Calculation_Functions::VALUE();
@@ -2161,6 +2194,8 @@ class PHPExcel_Calculation {
}
$result = array_shift($testResult);
}
+ self::$returnArrayAsType = $returnArrayAsType;
+
if ($result === NULL) {
return 0;
@@ -2198,15 +2233,16 @@ class PHPExcel_Calculation {
* @return mixed
* @throws PHPExcel_Calculation_Exception
*/
- public function calculateFormula($formula, $cellID=null, PHPExcel_Cell $pCell = null) {
+ public function calculateFormula($formula, $cellID=NULL, PHPExcel_Cell $pCell = NULL) {
// Initialise the logging settings
$this->formulaError = null;
- $this->debugLog = $this->debugLogStack = array();
+ $this->_debugLog->clearLog();
+ $this->_cyclicReferenceStack->clear();
// Disable calculation cacheing because it only applies to cell calculations, not straight formulae
// But don't actually flush any cache
$resetCache = $this->getCalculationCacheEnabled();
- self::$_calculationCacheEnabled = false;
+ $this->_calculationCacheEnabled = FALSE;
// Execute the calculation
try {
$result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell));
@@ -2215,12 +2251,33 @@ class PHPExcel_Calculation {
}
// Reset calculation cacheing to its previous state
- self::$_calculationCacheEnabled = $resetCache;
+ $this->_calculationCacheEnabled = $resetCache;
return $result;
} // function calculateFormula()
+ public function getValueFromCache($worksheetName, $cellID, &$cellValue) {
+ // Is calculation cacheing enabled?
+ // Is the value present in calculation cache?
+//echo 'Test cache for ',$worksheetName,'!',$cellID,PHP_EOL;
+ $this->_debugLog->writeDebugLog('Testing cache value for cell ', $worksheetName, '!', $cellID);
+ if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$worksheetName][$cellID]))) {
+//echo 'Retrieve from cache',PHP_EOL;
+ $this->_debugLog->writeDebugLog('Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache');
+ // Return the cached result
+ $cellValue = $this->_calculationCache[$worksheetName][$cellID];
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ public function saveValueToCache($worksheetName, $cellID, $cellValue) {
+ if ($this->_calculationCacheEnabled) {
+ $this->_calculationCache[$worksheetName][$cellID] = $cellValue;
+ }
+ }
+
/**
* Parse a cell formula and calculate its value
*
@@ -2231,45 +2288,23 @@ class PHPExcel_Calculation {
* @throws PHPExcel_Calculation_Exception
*/
public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) {
-// echo ''.$cellID.'
';
$cellValue = '';
// Basic validation that this is indeed a formula
- // We simply return the "cell value" (formula) if not
+ // We simply return the cell value if not
$formula = trim($formula);
if ($formula{0} != '=') return self::_wrapResult($formula);
$formula = ltrim(substr($formula,1));
if (!isset($formula{0})) return self::_wrapResult($formula);
- $wsTitle = "\x00Wrk";
- if ($pCell !== NULL) {
- $pCellParent = $pCell->getParent();
- if ($pCellParent !== NULL) {
- $wsTitle = $pCellParent->getTitle();
- }
- }
- // Is calculation cacheing enabled?
- if ($cellID !== NULL) {
- if (self::$_calculationCacheEnabled) {
- // Is the value present in calculation cache?
- $this->_writeDebug('Testing cache value for cell ', $cellID);
-// echo 'Testing cache value
';
- if (isset(self::$_calculationCache[$wsTitle][$cellID])) {
-// echo 'Value is in cache
';
- $this->_writeDebug('Retrieving value for ', $cellID, ' from cache');
- // Return the cached result
- $returnValue = self::$_calculationCache[$wsTitle][$cellID];
-// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
';
- if (is_array($returnValue)) {
- $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue);
- return array_shift($returnValue);
- }
- return $returnValue;
- }
- }
+ $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
+ $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk";
+
+ if (($cellID !== NULL) && ($this->getValueFromCache($wsTitle, $cellID, $cellValue))) {
+ return $cellValue;
}
- if ((in_array($wsTitle.'!'.$cellID,$this->debugLogStack)) && ($wsTitle != "\x00Wrk")) {
+ if (($wsTitle{0} !== "\x00") && ($this->_cyclicReferenceStack->onStack($wsTitle.'!'.$cellID))) {
if ($this->cyclicFormulaCount <= 0) {
return $this->_raiseFormulaError('Cyclic Reference in Formula');
} elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) &&
@@ -2287,16 +2322,15 @@ class PHPExcel_Calculation {
}
}
}
- $this->debugLogStack[] = $wsTitle.'!'.$cellID;
+
// Parse the formula onto the token stack and calculate the value
+ $this->_cyclicReferenceStack->push($wsTitle.'!'.$cellID);
$cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell);
- array_pop($this->debugLogStack);
+ $this->_cyclicReferenceStack->pop();
// Save to calculation cache
if ($cellID !== NULL) {
- if (self::$_calculationCacheEnabled) {
- self::$_calculationCache[$wsTitle][$cellID] = $cellValue;
- }
+ $this->saveValueToCache($wsTitle, $cellID, $cellValue);
}
// Return the calculated value
@@ -2457,7 +2491,7 @@ class PHPExcel_Calculation {
* @return mixed
*/
private function _showValue($value) {
- if ($this->writeDebugLog) {
+ if ($this->_debugLog->getWriteDebugLog()) {
$testArray = PHPExcel_Calculation_Functions::flattenArray($value);
if (count($testArray) == 1) {
$value = array_pop($testArray);
@@ -2492,7 +2526,7 @@ class PHPExcel_Calculation {
* @return mixed
*/
private function _showTypeDetails($value) {
- if ($this->writeDebugLog) {
+ if ($this->_debugLog->getWriteDebugLog()) {
$testArray = PHPExcel_Calculation_Functions::flattenArray($value);
if (count($testArray) == 1) {
$value = array_pop($testArray);
@@ -2527,15 +2561,15 @@ class PHPExcel_Calculation {
static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))');
// Convert any Excel matrix references to the MKMATRIX() function
- if (strpos($formula,'{') !== false) {
+ if (strpos($formula,'{') !== FALSE) {
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
- if (strpos($formula,'"') !== false) {
+ 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);
// Open and Closed counts used for trapping mismatched braces in the formula
$openCount = $closeCount = 0;
- $i = false;
+ $i = FALSE;
foreach($temp as &$value) {
// Only count/replace in alternating array entries
if ($i = !$i) {
@@ -2578,43 +2612,46 @@ class PHPExcel_Calculation {
} // function _mkMatrix()
+ // Binary Operators
+ // These operators always work on two values
+ // Array key is the operator, the value indicates whether this is a left or right associative operator
+ private static $_operatorAssociativity = array(
+ '^' => 0, // Exponentiation
+ '*' => 0, '/' => 0, // Multiplication and Division
+ '+' => 0, '-' => 0, // Addition and Subtraction
+ '&' => 0, // Concatenation
+ '|' => 0, ':' => 0, // Intersect and Range
+ '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison
+ );
+
+ // Comparison (Boolean) Operators
+ // These operators work on two values, but always return a boolean result
+ private static $_comparisonOperators = array('>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE);
+
+ // 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
+ private static $_operatorPrecedence = array(
+ ':' => 8, // Range
+ '|' => 7, // Intersect
+ '~' => 6, // Negation
+ '%' => 5, // Percentage
+ '^' => 4, // Exponentiation
+ '*' => 3, '/' => 3, // Multiplication and Division
+ '+' => 2, '-' => 2, // Addition and Subtraction
+ '&' => 1, // Concatenation
+ '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison
+ );
+
// Convert infix to postfix notation
- private function _parseFormula($formula, PHPExcel_Cell $pCell = null) {
- if (($formula = self::_convertMatrixReferences(trim($formula))) === false) {
+ private function _parseFormula($formula, PHPExcel_Cell $pCell = NULL) {
+ if (($formula = self::_convertMatrixReferences(trim($formula))) === 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 = ($pCell !== NULL) ? $pCell->getParent() : NULL;
-
- // Binary Operators
- // These operators always work on two values
- // Array key is the operator, the value indicates whether this is a left or right associative operator
- $operatorAssociativity = array('^' => 0, // Exponentiation
- '*' => 0, '/' => 0, // Multiplication and Division
- '+' => 0, '-' => 0, // Addition and Subtraction
- '&' => 0, // Concatenation
- '|' => 0, ':' => 0, // Intersect and Range
- '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison
- );
- // Comparison (Boolean) Operators
- // These operators work on two values, but always return a boolean result
- $comparisonOperators = array('>' => true, '<' => true, '=' => true, '>=' => true, '<=' => true, '<>' => true);
-
- // 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(':' => 8, // Range
- '|' => 7, // Intersect
- '~' => 6, // Negation
- '%' => 5, // Percentage
- '^' => 4, // Exponentiation
- '*' => 3, '/' => 3, // Multiplication and Division
- '+' => 2, '-' => 2, // Addition and Subtraction
- '&' => 1, // Concatenation
- '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison
- );
+ $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
$regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION.
'|'.self::CALCULATION_REGEXP_NUMBER.
@@ -2629,55 +2666,55 @@ class PHPExcel_Calculation {
$index = 0;
$stack = new PHPExcel_Calculation_Token_Stack;
$output = array();
- $expectingOperator = false; // We use this test in syntax-checking the expression to determine when a
+ $expectingOperator = FALSE; // We use this test in syntax-checking the expression to determine when a
// - is a negation or + is a positive operator rather than an operation
- $expectingOperand = false; // We use this test in syntax-checking the expression to determine whether an operand
+ $expectingOperand = FALSE; // We use this test in syntax-checking the expression to determine whether an operand
// should be null in a function call
// The guts of the lexical parser
// Loop through the formula extracting each operator and operand in turn
- while(true) {
-// echo 'Assessing Expression '.substr($formula, $index).'
';
+ while(TRUE) {
+//echo 'Assessing Expression '.substr($formula, $index),PHP_EOL;
$opCharacter = $formula{$index}; // Get the first character of the value at the current index position
-// echo 'Initial character of expression block is '.$opCharacter.'
';
- if ((isset($comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset($comparisonOperators[$formula{$index+1}]))) {
+//echo 'Initial character of expression block is '.$opCharacter,PHP_EOL;
+ if ((isset(self::$_comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$_comparisonOperators[$formula{$index+1}]))) {
$opCharacter .= $formula{++$index};
-// echo 'Initial character of expression block is comparison operator '.$opCharacter.'
';
+//echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL;
}
// Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand
$isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match);
-// echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').'
';
-// var_dump($match);
+//echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').PHP_EOL;
+//var_dump($match);
if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus?
-// echo 'Element is a Negation operator
';
+//echo 'Element is a Negation operator',PHP_EOL;
$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
';
+//echo 'Element is a Percentage operator',PHP_EOL;
$stack->push('Unary Operator','%'); // Put a percentage on the stack
++$index;
} elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded?
-// echo 'Element is a Positive number, not Plus operator
';
+//echo 'Element is a Positive number, not Plus operator',PHP_EOL;
++$index; // Drop the redundant plus symbol
} elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde or pipe, because they are legal
return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression
} elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack?
-// echo 'Element with value '.$opCharacter.' is an Operator
';
+//echo 'Element with value '.$opCharacter.' is an Operator',PHP_EOL;
while($stack->count() > 0 &&
($o2 = $stack->last()) &&
isset(self::$_operators[$o2['value']]) &&
- @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) {
+ @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) {
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
}
$stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack
++$index;
- $expectingOperator = false;
+ $expectingOperator = FALSE;
} elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis?
-// echo 'Element is a Closing bracket
';
- $expectingOperand = false;
+//echo 'Element is a Closing bracket',PHP_EOL;
+ $expectingOperand = FALSE;
while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
if ($o2 === NULL) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"');
else $output[] = $o2;
@@ -2685,65 +2722,65 @@ class PHPExcel_Calculation {
$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.'
';
+//echo 'Closed Function is '.$functionName,PHP_EOL;
$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) {
-// echo 'With 1 argument
';
-// } else {
-// echo 'With '.$argumentCount.' arguments
';
-// }
+//if ($argumentCount == 0) {
+// echo 'With no arguments',PHP_EOL;
+//} elseif ($argumentCount == 1) {
+// echo 'With 1 argument',PHP_EOL;
+//} else {
+// echo 'With '.$argumentCount.' arguments',PHP_EOL;
+//}
$output[] = $d; // Dump the argument count on the output
$output[] = $stack->pop(); // Pop the function and push onto the output
if (isset(self::$_controlFunctions[$functionName])) {
-// echo 'Built-in function '.$functionName.'
';
+//echo 'Built-in function '.$functionName,PHP_EOL;
$expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount'];
$functionCall = self::$_controlFunctions[$functionName]['functionCall'];
} elseif (isset(self::$_PHPExcelFunctions[$functionName])) {
-// echo 'PHPExcel function '.$functionName.'
';
+//echo 'PHPExcel function '.$functionName,PHP_EOL;
$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");
}
// Check the argument count
- $argumentCountError = false;
+ $argumentCountError = FALSE;
if (is_numeric($expectedArgumentCount)) {
if ($expectedArgumentCount < 0) {
-// echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount).'
';
+//echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount),PHP_EOL;
if ($argumentCount > abs($expectedArgumentCount)) {
- $argumentCountError = true;
+ $argumentCountError = TRUE;
$expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount);
}
} else {
-// echo '$expectedArgumentCount is numeric '.$expectedArgumentCount.'
';
+//echo '$expectedArgumentCount is numeric '.$expectedArgumentCount,PHP_EOL;
if ($argumentCount != $expectedArgumentCount) {
- $argumentCountError = true;
+ $argumentCountError = TRUE;
$expectedArgumentCountString = $expectedArgumentCount;
}
}
} elseif ($expectedArgumentCount != '*') {
$isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch);
-// print_r($argMatch);
-// echo '
';
+//print_r($argMatch);
+//echo PHP_EOL;
switch ($argMatch[2]) {
case '+' :
if ($argumentCount < $argMatch[1]) {
- $argumentCountError = true;
+ $argumentCountError = TRUE;
$expectedArgumentCountString = $argMatch[1].' or more ';
}
break;
case '-' :
if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) {
- $argumentCountError = true;
+ $argumentCountError = TRUE;
$expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3];
}
break;
case ',' :
if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) {
- $argumentCountError = true;
+ $argumentCountError = TRUE;
$expectedArgumentCountString = 'either '.$argMatch[1].' or '.$argMatch[3];
}
break;
@@ -2756,7 +2793,7 @@ class PHPExcel_Calculation {
++$index;
} elseif ($opCharacter == ',') { // Is this the separator for function arguments?
-// echo 'Element is a Function argument separator
';
+//echo 'Element is a Function argument separator',PHP_EOL;
while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
if ($o2 === NULL) return $this->_raiseFormulaError("Formula Error: Unexpected ,");
else $output[] = $o2; // pop the argument expression stuff and push onto the output
@@ -2764,7 +2801,7 @@ class PHPExcel_Calculation {
// 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' => self::$_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);
@@ -2773,8 +2810,8 @@ class PHPExcel_Calculation {
$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;
+ $expectingOperator = FALSE;
+ $expectingOperand = TRUE;
++$index;
} elseif ($opCharacter == '(' && !$expectingOperator) {
@@ -2783,8 +2820,8 @@ class PHPExcel_Calculation {
++$index;
} elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number?
- $expectingOperator = true;
- $expectingOperand = false;
+ $expectingOperator = TRUE;
+ $expectingOperand = FALSE;
$val = $match[1];
$length = strlen($val);
// echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function
';
@@ -2797,14 +2834,14 @@ class PHPExcel_Calculation {
$ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch);
if ($ax) {
$stack->push('Operand Count for Function '.strtoupper($val).')', 0);
- $expectingOperator = true;
+ $expectingOperator = TRUE;
} else {
$stack->push('Operand Count for Function '.strtoupper($val).')', 1);
- $expectingOperator = false;
+ $expectingOperator = FALSE;
}
$stack->push('Brace', '(');
} else { // it's a var w/ implicit multiplication
- $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => null);
+ $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
';
@@ -2829,7 +2866,7 @@ class PHPExcel_Calculation {
}
$output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $val);
-// $expectingOperator = false;
+// $expectingOperator = FALSE;
} else { // it's a variable, constant, string, number or boolean
// echo 'Element is a Variable, Constant, String, Number or Boolean
';
// If the last entry on the stack was a : operator, then we may have a row or column range reference
@@ -2837,12 +2874,12 @@ class PHPExcel_Calculation {
if ($testPrevOp['value'] == ':') {
$startRowColRef = $output[count($output)-1]['value'];
$rangeWS1 = '';
- if (strpos('!',$startRowColRef) !== false) {
+ if (strpos('!',$startRowColRef) !== FALSE) {
list($rangeWS1,$startRowColRef) = explode('!',$startRowColRef);
}
if ($rangeWS1 != '') $rangeWS1 .= '!';
$rangeWS2 = $rangeWS1;
- if (strpos('!',$val) !== false) {
+ if (strpos('!',$val) !== FALSE) {
list($rangeWS2,$val) = explode('!',$val);
}
if ($rangeWS2 != '') $rangeWS2 .= '!';
@@ -2861,14 +2898,14 @@ class PHPExcel_Calculation {
}
}
- $localeConstant = false;
+ $localeConstant = FALSE;
if ($opCharacter == '"') {
// echo 'Element is a String
';
// 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)) {
+ 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 {
@@ -2879,11 +2916,11 @@ class PHPExcel_Calculation {
$excelConstant = trim(strtoupper($val));
// echo 'Element '.$excelConstant.' is an Excel Constant
';
$val = self::$_ExcelConstants[$excelConstant];
- } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== false) {
+ } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== FALSE) {
// echo 'Element '.$localeConstant.' is an Excel Constant
';
$val = self::$_ExcelConstants[$localeConstant];
}
- $details = array('type' => 'Value', 'value' => $val, 'reference' => null);
+ $details = array('type' => 'Value', 'value' => $val, 'reference' => NULL);
if ($localeConstant) { $details['localeValue'] = $localeConstant; }
$output[] = $details;
}
@@ -2893,9 +2930,9 @@ class PHPExcel_Calculation {
++$index;
} elseif ($opCharacter == ')') { // miscellaneous error checking
if ($expectingOperand) {
- $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => null);
- $expectingOperand = false;
- $expectingOperator = true;
+ $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL);
+ $expectingOperand = FALSE;
+ $expectingOperator = TRUE;
} else {
return $this->_raiseFormulaError("Formula Error: Unexpected ')'");
}
@@ -2931,11 +2968,11 @@ class PHPExcel_Calculation {
while($stack->count() > 0 &&
($o2 = $stack->last()) &&
isset(self::$_operators[$o2['value']]) &&
- @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) {
+ @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_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;
+ $expectingOperator = FALSE;
}
}
}
@@ -2965,11 +3002,12 @@ class PHPExcel_Calculation {
}
// evaluate postfix notation
- private function _processTokenStack($tokens, $cellID = null, PHPExcel_Cell $pCell = null) {
- if ($tokens == false) return false;
+ 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
+ // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent cell collection),
+ // so we store the parent cell collection so that we can re-attach it when necessary
+ $pCellWorksheet = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL;
$pCellParent = ($pCell !== NULL) ? $pCell->getParent() : null;
$stack = new PHPExcel_Calculation_Token_Stack;
@@ -2991,9 +3029,9 @@ class PHPExcel_Calculation {
// Log what we're doing
if ($token == ':') {
- $this->_writeDebug('Evaluating Range ', $this->_showValue($operand1Data['reference']), ' ', $token, ' ', $this->_showValue($operand2Data['reference']));
+ $this->_debugLog->writeDebugLog('Evaluating Range ', $this->_showValue($operand1Data['reference']), ' ', $token, ' ', $this->_showValue($operand2Data['reference']));
} else {
- $this->_writeDebug('Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2));
+ $this->_debugLog->writeDebugLog('Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2));
}
// Process the operation in the appropriate manner
@@ -3010,12 +3048,12 @@ class PHPExcel_Calculation {
// Binary Operators
case ':' : // Range
$sheet1 = $sheet2 = '';
- if (strpos($operand1Data['reference'],'!') !== false) {
+ if (strpos($operand1Data['reference'],'!') !== FALSE) {
list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']);
} else {
- $sheet1 = ($pCellParent !== NULL) ? $pCellParent->getTitle() : '';
+ $sheet1 = ($pCellParent !== NULL) ? $pCellWorksheet->getTitle() : '';
}
- if (strpos($operand2Data['reference'],'!') !== false) {
+ if (strpos($operand2Data['reference'],'!') !== FALSE) {
list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']);
} else {
$sheet2 = $sheet1;
@@ -3049,13 +3087,13 @@ class PHPExcel_Calculation {
}
$cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow);
if ($pCellParent !== NULL) {
- $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($sheet1), false);
+ $cellValue = $this->extractCellRange($cellRef, $this->_workbook->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);
+ $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL);
}
break;
@@ -3094,13 +3132,13 @@ class PHPExcel_Calculation {
$matrixResult = $matrix->concat($operand2);
$result = $matrixResult->getArray();
} catch (PHPExcel_Exception $ex) {
- $this->_writeDebug('JAMA Matrix Exception: ', $ex->getMessage());
+ $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
$result = '#VALUE!';
}
} else {
$result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"';
}
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result));
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
$stack->push('Value',$result);
break;
case '|' : // Intersect
@@ -3114,7 +3152,7 @@ class PHPExcel_Calculation {
}
}
$cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow);
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($cellIntersect));
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($cellIntersect));
$stack->push('Value',$cellIntersect,$cellRef);
break;
}
@@ -3126,11 +3164,11 @@ class PHPExcel_Calculation {
$arg = $arg['value'];
if ($token === '~') {
// echo 'Token is a negation operator
';
- $this->_writeDebug('Evaluating Negation of ', $this->_showValue($arg));
+ $this->_debugLog->writeDebugLog('Evaluating Negation of ', $this->_showValue($arg));
$multiplier = -1;
} else {
// echo 'Token is a percentile operator
';
- $this->_writeDebug('Evaluating Percentile of ', $this->_showValue($arg));
+ $this->_debugLog->writeDebugLog('Evaluating Percentile of ', $this->_showValue($arg));
$multiplier = 0.01;
}
if (is_array($arg)) {
@@ -3140,17 +3178,17 @@ class PHPExcel_Calculation {
$matrixResult = $matrix1->arrayTimesEquals($multiplier);
$result = $matrixResult->getArray();
} catch (PHPExcel_Exception $ex) {
- $this->_writeDebug('JAMA Matrix Exception: ', $ex->getMessage());
+ $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
$result = '#VALUE!';
}
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result));
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
$stack->push('Value',$result);
} else {
$this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack);
}
} elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) {
- $cellRef = null;
+ $cellRef = NULL;
// echo 'Element '.$token.' is a Cell reference
';
if (isset($matches[8])) {
// echo 'Reference is a Range of cells
';
@@ -3161,29 +3199,29 @@ class PHPExcel_Calculation {
$cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10];
if ($matches[2] > '') {
$matches[2] = trim($matches[2],"\"'");
- if ((strpos($matches[2],'[') !== false) || (strpos($matches[2],']') !== false)) {
+ if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) {
// It's a Reference to an external workbook (not currently supported)
return $this->_raiseFormulaError('Unable to access External Workbook');
}
$matches[2] = trim($matches[2],"\"'");
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
';
- $this->_writeDebug('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]);
+ $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]);
if ($pCellParent !== NULL) {
- $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false);
+ $cellValue = $this->extractCellRange($cellRef, $this->_workbook->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 ', $this->_showTypeDetails($cellValue));
+ $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
// $cellRef = $matches[2].'!'.$cellRef;
} else {
// echo '$cellRef='.$cellRef.' in current worksheet
';
- $this->_writeDebug('Evaluating Cell Range ', $cellRef, ' in current worksheet');
+ $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet');
if ($pCellParent !== NULL) {
- $cellValue = $this->extractCellRange($cellRef, $pCellParent, false);
+ $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE);
} else {
return $this->_raiseFormulaError('Unable to access Cell Reference');
}
- $this->_writeDebug('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
+ $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
}
}
} else {
@@ -3195,34 +3233,34 @@ class PHPExcel_Calculation {
$cellRef = $matches[6].$matches[7];
if ($matches[2] > '') {
$matches[2] = trim($matches[2],"\"'");
- if ((strpos($matches[2],'[') !== false) || (strpos($matches[2],']') !== false)) {
+ if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) {
// It's a Reference to an external workbook (not currently supported)
return $this->_raiseFormulaError('Unable to access External Workbook');
}
// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
';
- $this->_writeDebug('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]);
+ $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]);
if ($pCellParent !== NULL) {
- if ($pCellParent->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) {
- $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false);
+ if ($this->_workbook->getSheetByName($matches[2])->cellExists($cellRef)) {
+ $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE);
$pCell->attach($pCellParent);
} else {
- $cellValue = null;
+ $cellValue = NULL;
}
} else {
return $this->_raiseFormulaError('Unable to access Cell Reference');
}
- $this->_writeDebug('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
+ $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue));
// $cellRef = $matches[2].'!'.$cellRef;
} else {
// echo '$cellRef='.$cellRef.' in current worksheet
';
- $this->_writeDebug('Evaluating Cell ', $cellRef, ' in current worksheet');
- if ($pCellParent->cellExists($cellRef)) {
- $cellValue = $this->extractCellRange($cellRef, $pCellParent, false);
+ $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in current worksheet');
+ if ($pCellParent->isDataSet($cellRef)) {
+ $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE);
$pCell->attach($pCellParent);
} else {
- $cellValue = null;
+ $cellValue = NULL;
}
- $this->_writeDebug('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
+ $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue));
}
}
}
@@ -3235,7 +3273,7 @@ class PHPExcel_Calculation {
$argCount = $stack->pop();
$argCount = $argCount['value'];
if ($functionName != 'MKMATRIX') {
- $this->_writeDebug('Evaluating Function ', self::_localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's'));
+ $this->_debugLog->writeDebugLog('Evaluating Function ', self::_localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's'));
}
if ((isset(self::$_PHPExcelFunctions[$functionName])) || (isset(self::$_controlFunctions[$functionName]))) { // function
if (isset(self::$_PHPExcelFunctions[$functionName])) {
@@ -3278,30 +3316,30 @@ class PHPExcel_Calculation {
// print_r($args);
// echo '
';
if ($functionName != 'MKMATRIX') {
- if ($this->writeDebugLog) {
+ if ($this->_debugLog->getWriteDebugLog()) {
krsort($argArrayVals);
- $this->_writeDebug('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)), ' )');
+ $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($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('Argument is a matrix: ', $this->_showValue($operand1));
+// $this->_debugLog->writeDebugLog('Argument is a matrix: ', $this->_showValue($operand1));
// $result = array();
// $row = 0;
// foreach($operand1 as $args) {
// if (is_array($args)) {
// foreach($args as $arg) {
-// $this->_writeDebug('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )');
+// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )');
// $r = call_user_func_array($functionCall,$arg);
-// $this->_writeDebug('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
+// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
// $result[$row][] = $r;
// }
// ++$row;
// } else {
-// $this->_writeDebug('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )');
+// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )');
// $r = call_user_func_array($functionCall,$args);
-// $this->_writeDebug('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
+// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r));
// $result[] = $r;
// }
// }
@@ -3310,7 +3348,7 @@ class PHPExcel_Calculation {
if ($passCellReference) {
$args[] = $pCell;
}
- if (strpos($functionCall,'::') !== false) {
+ if (strpos($functionCall,'::') !== FALSE) {
$result = call_user_func_array(explode('::',$functionCall),$args);
} else {
foreach($args as &$arg) {
@@ -3321,7 +3359,7 @@ class PHPExcel_Calculation {
}
// }
if ($functionName != 'MKMATRIX') {
- $this->_writeDebug('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result));
+ $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result));
}
$stack->push('Value',self::_wrapResult($result));
}
@@ -3332,7 +3370,7 @@ class PHPExcel_Calculation {
$excelConstant = strtoupper($token);
// echo 'Token is a PHPExcel constant: '.$excelConstant.'
';
$stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]);
- $this->_writeDebug('Evaluating Constant ', $excelConstant, ' as ', $this->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
+ $this->_debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->_showTypeDetails(self::$_ExcelConstants[$excelConstant]));
} elseif ((is_numeric($token)) || ($token === NULL) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) {
// echo 'Token is a number, boolean, string, null or an Excel error
';
$stack->push('Value',$token);
@@ -3341,10 +3379,10 @@ class PHPExcel_Calculation {
// echo 'Token is a named range
';
$namedRange = $matches[6];
// echo 'Named Range is '.$namedRange.'
';
- $this->_writeDebug('Evaluating Named Range ', $namedRange);
- $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCellParent : null), false);
+ $this->_debugLog->writeDebugLog('Evaluating Named Range ', $namedRange);
+ $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellWorksheet : NULL), FALSE);
$pCell->attach($pCellParent);
- $this->_writeDebug('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue));
+ $this->_debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue));
$stack->push('Named Range',$cellValue,$namedRange);
} else {
return $this->_raiseFormulaError("undefined variable '$token'");
@@ -3363,7 +3401,7 @@ class PHPExcel_Calculation {
} // function _processTokenStack()
- private function _validateBinaryOperand($cellID,&$operand,&$stack) {
+ private function _validateBinaryOperand($cellID, &$operand, &$stack) {
// 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
@@ -3374,36 +3412,36 @@ class PHPExcel_Calculation {
// 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('Value', $operand);
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($operand));
- return false;
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($operand));
+ return FALSE;
} 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 ', $this->_showTypeDetails('#VALUE!'));
- return false;
+ $this->_debugLog->writeDebugLog('Evaluation Result is a ', $this->_showTypeDetails('#VALUE!'));
+ return FALSE;
}
}
}
// return a true if the value of the operand is one that we can use in normal binary operations
- return true;
+ return TRUE;
} // function _validateBinaryOperand()
- private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack,$recursingArrays=false) {
+ 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 Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2));
+ $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_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 Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData));
+ $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData));
$this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack);
$r = $stack->pop();
$result[$x] = $r['value'];
@@ -3411,17 +3449,17 @@ class PHPExcel_Calculation {
} else {
if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); }
foreach($operand1 as $x => $operandData) {
- $this->_writeDebug('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2[$x]));
- $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,true);
+ $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_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('Comparison Evaluation Result is ', $this->_showTypeDetails($result));
+ $this->_debugLog->writeDebugLog('Comparison Evaluation Result is ', $this->_showTypeDetails($result));
// And push the result onto the stack
$stack->push('Array',$result);
- return true;
+ return TRUE;
}
// Simple validate the two operands if they are string values
@@ -3457,31 +3495,31 @@ class PHPExcel_Calculation {
}
// Log the result details
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result));
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
// And push the result onto the stack
$stack->push('Value',$result);
- return true;
+ 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;
- if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return false;
+ if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return FALSE;
+ if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return FALSE;
- $executeMatrixOperation = 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;
+ $executeMatrixOperation = TRUE;
$mSize = array();
list($mSize[],$mSize[],$mSize[],$mSize[]) = 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;
+ $executeMatrixOperation = FALSE;
$operand1 = $operand1[0][0];
$operand2 = $operand2[0][0];
}
@@ -3495,7 +3533,7 @@ class PHPExcel_Calculation {
$matrixResult = $matrix->$matrixFunction($operand2);
$result = $matrixResult->getArray();
} catch (PHPExcel_Exception $ex) {
- $this->_writeDebug('JAMA Matrix Exception: ', $ex->getMessage());
+ $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage());
$result = '#VALUE!';
}
} else {
@@ -3522,8 +3560,8 @@ class PHPExcel_Calculation {
if ($operand2 == 0) {
// Trap for Divide by Zero error
$stack->push('Value','#DIV/0!');
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!'));
- return false;
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!'));
+ return FALSE;
} else {
$result = $operand1/$operand2;
}
@@ -3537,29 +3575,17 @@ class PHPExcel_Calculation {
}
// Log the result details
- $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result));
+ $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result));
// And push the result onto the stack
$stack->push('Value',$result);
- return true;
+ return TRUE;
} // function _executeNumericBinaryOperation()
- private function _writeDebug() {
- // Only write the debug log if logging is enabled
- if ($this->writeDebugLog) {
- $message = implode('',func_get_args());
- if ($this->echoDebugLog) {
- echo implode(' -> ',$this->debugLogStack).' -> '.$message,'
';
- }
- $this->debugLog[] = implode(' -> ',$this->debugLogStack).' -> '.$message;
- }
- } // function _writeDebug()
-
-
// trigger an error, but nicely, if need be
protected function _raiseFormulaError($errorMessage) {
$this->formulaError = $errorMessage;
- $this->debugLogStack = array();
+ $this->_cyclicReferenceStack->clear();
if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage);
trigger_error($errorMessage, E_USER_ERROR);
} // function _raiseFormulaError()
@@ -3573,44 +3599,45 @@ class PHPExcel_Calculation {
* @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
* @throws PHPExcel_Calculation_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 ();
-// echo 'extractCellRange('.$pRange.')
';
+// echo 'extractCellRange('.$pRange.')',PHP_EOL;
if ($pSheet !== NULL) {
-// echo 'Passed sheet name is '.$pSheet->getTitle().'
';
-// echo 'Range reference is '.$pRange.'
';
+ $pSheetName = $pSheet->getTitle();
+// echo 'Passed sheet name is '.$pSheetName.PHP_EOL;
+// echo 'Range reference is '.$pRange.PHP_EOL;
if (strpos ($pRange, '!') !== false) {
-// echo '$pRange reference includes sheet reference
';
- $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
- $pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]);
-// echo 'New sheet name is '.$pSheet->getTitle().'
';
- $pRange = $worksheetReference[1];
-// echo 'Adjusted Range reference is '.$pRange.'
';
+// echo '$pRange reference includes sheet reference',PHP_EOL;
+ list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
+// echo 'New sheet name is '.$pSheetName,PHP_EOL;
+// echo 'Adjusted Range reference is '.$pRange,PHP_EOL;
+ $pSheet = $this->_workbook->getSheetByName($pSheetName);
}
// Extract range
$aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange);
- $pRange = $pSheet->getTitle().'!'.$pRange;
+ $pRange = $pSheetName.'!'.$pRange;
if (!isset($aReferences[1])) {
// Single cell in range
list($currentCol,$currentRow) = sscanf($aReferences[0],'%[A-Z]%d');
+ $cellValue = NULL;
if ($pSheet->cellExists($aReferences[0])) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
} else {
- $returnValue[$currentRow][$currentCol] = null;
+ $returnValue[$currentRow][$currentCol] = NULL;
}
} else {
// Extract cell data for all cells in the range
foreach ($aReferences as $reference) {
// Extract range
list($currentCol,$currentRow) = sscanf($reference,'%[A-Z]%d');
-
+ $cellValue = NULL;
if ($pSheet->cellExists($reference)) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
} else {
- $returnValue[$currentRow][$currentCol] = null;
+ $returnValue[$currentRow][$currentCol] = NULL;
}
}
}
@@ -3629,21 +3656,21 @@ class PHPExcel_Calculation {
* @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned.
* @throws PHPExcel_Calculation_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 ();
// echo 'extractNamedRange('.$pRange.')
';
if ($pSheet !== NULL) {
-// echo 'Current sheet name is '.$pSheet->getTitle().'
';
+ $pSheetName = $pSheet->getTitle();
+// echo 'Current sheet name is '.$pSheetName.'
';
// echo 'Range reference is '.$pRange.'
';
if (strpos ($pRange, '!') !== false) {
-// echo '$pRange reference includes sheet reference
';
- $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
- $pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]);
-// echo 'New sheet name is '.$pSheet->getTitle().'
';
- $pRange = $worksheetReference[1];
-// echo 'Adjusted Range reference is '.$pRange.'
';
+// echo '$pRange reference includes sheet reference',PHP_EOL;
+ list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true);
+// echo 'New sheet name is '.$pSheetName,PHP_EOL;
+// echo 'Adjusted Range reference is '.$pRange,PHP_EOL;
+ $pSheet = $this->_workbook->getSheetByName($pSheetName);
}
// Named range?
@@ -3678,10 +3705,11 @@ class PHPExcel_Calculation {
if (!isset($aReferences[1])) {
// Single cell (or single column or row) in range
list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]);
+ $cellValue = NULL;
if ($pSheet->cellExists($aReferences[0])) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
} else {
- $returnValue[$currentRow][$currentCol] = null;
+ $returnValue[$currentRow][$currentCol] = NULL;
}
} else {
// Extract cell data for all cells in the range
@@ -3689,10 +3717,11 @@ class PHPExcel_Calculation {
// Extract range
list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference);
// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
';
+ $cellValue = NULL;
if ($pSheet->cellExists($reference)) {
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
} else {
- $returnValue[$currentRow][$currentCol] = null;
+ $returnValue[$currentRow][$currentCol] = NULL;
}
}
}
@@ -3716,7 +3745,7 @@ class PHPExcel_Calculation {
if (isset(self::$_PHPExcelFunctions[$pFunction])) {
return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY');
} else {
- return false;
+ return FALSE;
}
} // function isImplemented()
diff --git a/Classes/PHPExcel/Calculation/Token/Stack.php b/Classes/PHPExcel/Calculation/Token/Stack.php
index 081a38dc..bdf9d555 100644
--- a/Classes/PHPExcel/Calculation/Token/Stack.php
+++ b/Classes/PHPExcel/Calculation/Token/Stack.php
@@ -67,7 +67,9 @@ class PHPExcel_Calculation_Token_Stack {
} // function last()
- function __construct() {
+ function clear() {
+ $this->_stack = array();
+ $this->_count = 0;
}
} // class PHPExcel_Calculation_Token_Stack
diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php
index 2e9cd327..cbaddc15 100644
--- a/Classes/PHPExcel/Cell.php
+++ b/Classes/PHPExcel/Cell.php
@@ -50,13 +50,6 @@ class PHPExcel_Cell
*/
private static $_valueBinder = NULL;
- /**
- * Cell Address (e.g. A1)
- *
- * @var string
- */
- private $_coordinate;
-
/**
* Value of the cell
*
@@ -86,7 +79,7 @@ class PHPExcel_Cell
/**
* Parent worksheet
*
- * @var PHPExcel_Worksheet
+ * @var PHPExcel_CachedObjectStorage_CacheBase
*/
private $_parent;
@@ -110,7 +103,8 @@ class PHPExcel_Cell
* @return void
**/
public function notifyCacheController() {
- $this->_parent->getCellCacheController()->updateCacheData($this);
+ $this->_parent->updateCacheData($this);
+
return $this;
}
@@ -118,7 +112,9 @@ class PHPExcel_Cell
$this->_parent = NULL;
}
- public function attach($parent) {
+ public function attach(PHPExcel_CachedObjectStorage_CacheBase $parent) {
+
+
$this->_parent = $parent;
}
@@ -126,23 +122,18 @@ class PHPExcel_Cell
/**
* Create a new Cell
*
- * @param string $pColumn
- * @param int $pRow
* @param mixed $pValue
* @param string $pDataType
* @param PHPExcel_Worksheet $pSheet
* @throws PHPExcel_Exception
*/
- public function __construct($pCoordinate = 'A1', $pValue = NULL, $pDataType = NULL, PHPExcel_Worksheet $pSheet = NULL)
+ public function __construct($pValue = NULL, $pDataType = NULL, PHPExcel_Worksheet $pSheet = NULL)
{
- // Initialise cell coordinate
- $this->_coordinate = strtoupper($pCoordinate);
-
// Initialise cell value
$this->_value = $pValue;
- // Set worksheet
- $this->_parent = $pSheet;
+ // Set worksheet cache
+ $this->_parent = $pSheet->getCellCacheController();
// Set datatype?
if ($pDataType !== NULL) {
@@ -166,8 +157,7 @@ class PHPExcel_Cell
*/
public function getColumn()
{
- list($column) = sscanf($this->_coordinate, '%[A-Z]%d');
- return $column;
+ return $this->_parent->getCurrentColumn();
}
/**
@@ -177,8 +167,7 @@ class PHPExcel_Cell
*/
public function getRow()
{
- list(,$row) = sscanf($this->_coordinate, '%[A-Z]%d');
- return $row;
+ return $this->_parent->getCurrentRow();
}
/**
@@ -188,7 +177,7 @@ class PHPExcel_Cell
*/
public function getCoordinate()
{
- return $this->_coordinate;
+ return $this->_parent->getCurrentAddress();
}
/**
@@ -210,7 +199,7 @@ class PHPExcel_Cell
{
return (string) PHPExcel_Style_NumberFormat::toFormattedString(
$this->getCalculatedValue(),
- $this->_parent->getParent()->getCellXfByIndex($this->getXfIndex())
+ $this->getWorksheet()->getParent()->getCellXfByIndex($this->getXfIndex())
->getNumberFormat()->getFormatCode()
);
}
@@ -284,31 +273,39 @@ class PHPExcel_Cell
*/
public function getCalculatedValue($resetLog = TRUE)
{
-// echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().'
';
+//echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().PHP_EOL;
if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) {
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.'
';
+//echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value'.PHP_EOL;
+ $result = PHPExcel_Calculation::getInstance(
+ $this->getWorksheet()->getParent()
+ )->calculateCellValue($this,$resetLog);
+//echo $this->getCoordinate().' calculation result is '.$result.PHP_EOL;
+ // We don't yet handle array returns
+ if (is_array($result)) {
+ while (is_array($result)) {
+ $result = array_pop($result);
+ }
+ }
} catch ( PHPExcel_Exception $ex ) {
if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) {
-// echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'
';
+//echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL;
return $this->_calculatedValue; // Fallback for calculations referencing external files.
}
-// echo 'Calculation Exception: '.$ex->getMessage().'
';
+//echo 'Calculation Exception: '.$ex->getMessage().PHP_EOL;
$result = '#N/A';
throw(
new PHPExcel_Calculation_Exception(
- $this->getParent()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage()
+ $this->getWorksheet()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage()
)
);
}
if ($result === '#Not Yet Implemented') {
-// echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'
';
+//echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL;
return $this->_calculatedValue; // Fallback if calculation engine does not support the formula.
}
-// echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().'
';
+//echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().PHP_EOL;
return $result;
}
@@ -388,7 +385,7 @@ class PHPExcel_Cell
throw new PHPExcel_Exception('Cannot check for data validation when cell is not bound to a worksheet');
}
- return $this->_parent->dataValidationExists($this->getCoordinate());
+ return $this->getWorksheet()->dataValidationExists($this->getCoordinate());
}
/**
@@ -403,7 +400,7 @@ class PHPExcel_Cell
throw new PHPExcel_Exception('Cannot get data validation for cell that is not bound to a worksheet');
}
- return $this->_parent->getDataValidation($this->getCoordinate());
+ return $this->getWorksheet()->getDataValidation($this->getCoordinate());
}
/**
@@ -419,7 +416,7 @@ class PHPExcel_Cell
throw new PHPExcel_Exception('Cannot set data validation for cell that is not bound to a worksheet');
}
- $this->_parent->setDataValidation($this->getCoordinate(), $pDataValidation);
+ $this->getWorksheet()->setDataValidation($this->getCoordinate(), $pDataValidation);
return $this->notifyCacheController();
}
@@ -436,7 +433,7 @@ class PHPExcel_Cell
throw new PHPExcel_Exception('Cannot check for hyperlink when cell is not bound to a worksheet');
}
- return $this->_parent->hyperlinkExists($this->getCoordinate());
+ return $this->getWorksheet()->hyperlinkExists($this->getCoordinate());
}
/**
@@ -451,7 +448,7 @@ class PHPExcel_Cell
throw new PHPExcel_Exception('Cannot get hyperlink for cell that is not bound to a worksheet');
}
- return $this->_parent->getHyperlink($this->getCoordinate());
+ return $this->getWorksheet()->getHyperlink($this->getCoordinate());
}
/**
@@ -467,7 +464,7 @@ class PHPExcel_Cell
throw new PHPExcel_Exception('Cannot set hyperlink for cell that is not bound to a worksheet');
}
- $this->_parent->setHyperlink($this->getCoordinate(), $pHyperlink);
+ $this->getWorksheet()->setHyperlink($this->getCoordinate(), $pHyperlink);
return $this->notifyCacheController();
}
@@ -481,6 +478,15 @@ class PHPExcel_Cell
return $this->_parent;
}
+ /**
+ * Get parent worksheet
+ *
+ * @return PHPExcel_Worksheet
+ */
+ public function getWorksheet() {
+ return $this->_parent->getParent();
+ }
+
/**
* Re-bind parent
*
@@ -488,7 +494,7 @@ class PHPExcel_Cell
* @return PHPExcel_Cell
*/
public function rebindParent(PHPExcel_Worksheet $parent) {
- $this->_parent = $parent;
+ $this->_parent = $parent->getCellCacheController();
return $this->notifyCacheController();
}
@@ -859,11 +865,11 @@ class PHPExcel_Cell
*/
public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b)
{
- if ($a->_row < $b->_row) {
+ if ($a->getRow() < $b->getRow()) {
return -1;
- } elseif ($a->_row > $b->_row) {
+ } elseif ($a->getRow() > $b->getRow()) {
return 1;
- } elseif (self::columnIndexFromString($a->_column) < self::columnIndexFromString($b->_column)) {
+ } elseif (self::columnIndexFromString($a->getColumn()) < self::columnIndexFromString($b->getColumn())) {
return -1;
} else {
return 1;
diff --git a/Classes/PHPExcel/Cell/AdvancedValueBinder.php b/Classes/PHPExcel/Cell/AdvancedValueBinder.php
index 0b5efec0..9c96a1b9 100644
--- a/Classes/PHPExcel/Cell/AdvancedValueBinder.php
+++ b/Classes/PHPExcel/Cell/AdvancedValueBinder.php
@@ -86,7 +86,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
if ($matches[1] == '-') $value = 0 - $value;
$cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode( '??/??' );
return true;
} elseif (preg_match('/^([+-]?)([0-9]*) +([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) {
@@ -95,7 +95,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
if ($matches[1] == '-') $value = 0 - $value;
$cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode( '# ??/??' );
return true;
}
@@ -106,7 +106,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
$value = (float) str_replace('%', '', $value) / 100;
$cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00 );
return true;
}
@@ -120,7 +120,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
$value = (float) trim(str_replace(array($currencyCode, $thousandsSeparator, $decimalSeparator), array('', '', '.'), $value));
$cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode(
str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE )
);
@@ -130,7 +130,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
$value = (float) trim(str_replace(array('$',','), '', $value));
$cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE );
return true;
}
@@ -142,7 +142,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
$days = $h / 24 + $m / 1440;
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 );
return true;
}
@@ -155,7 +155,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
// Convert value to number
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 );
return true;
}
@@ -170,7 +170,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
} else {
$formatCode = 'yyyy-mm-dd';
}
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getNumberFormat()->setFormatCode($formatCode);
return true;
}
@@ -180,7 +180,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder
$value = PHPExcel_Shared_String::SanitizeUTF8($value);
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING);
// Set style
- $cell->getParent()->getStyle( $cell->getCoordinate() )
+ $cell->getWorksheet()->getStyle( $cell->getCoordinate() )
->getAlignment()->setWrapText(TRUE);
return true;
}
diff --git a/Classes/PHPExcel/Chart/DataSeriesValues.php b/Classes/PHPExcel/Chart/DataSeriesValues.php
index 4a206482..034ac9e2 100644
--- a/Classes/PHPExcel/Chart/DataSeriesValues.php
+++ b/Classes/PHPExcel/Chart/DataSeriesValues.php
@@ -279,7 +279,7 @@ class PHPExcel_Chart_DataSeriesValues
public function refresh(PHPExcel_Worksheet $worksheet, $flatten = TRUE) {
if ($this->_dataSource !== NULL) {
- $calcEngine = PHPExcel_Calculation::getInstance();
+ $calcEngine = PHPExcel_Calculation::getInstance($worksheet->getParent());
$newDataValues = PHPExcel_Calculation::_unwrapResult(
$calcEngine->_calculateFormulaValue(
'='.$this->_dataSource,
diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php
index 5357a938..9791ead2 100644
--- a/Classes/PHPExcel/Worksheet.php
+++ b/Classes/PHPExcel/Worksheet.php
@@ -204,7 +204,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @var PHPExcel_Worksheet_AutoFilter
*/
- private $_autoFilter = null;
+ private $_autoFilter = NULL;
/**
* Freeze pane
@@ -362,12 +362,12 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
$this->_protection = new PHPExcel_Worksheet_Protection();
// Default row dimension
- $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(null);
+ $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(NULL);
// Default column dimension
- $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(null);
+ $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(NULL);
- $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(null, $this);
+ $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(NULL, $this);
}
@@ -376,11 +376,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* typically so that the worksheet object can be unset
*
*/
- public function disconnectCells()
- {
- if ( $this->_cellCollection != null ){
+ public function disconnectCells() {
+ if ( $this->_cellCollection !== NULL){
$this->_cellCollection->unsetWorksheetCells();
- $this->_cellCollection = null;
+ $this->_cellCollection = NULL;
}
// detach ourself from the workbook, so that it can then delete this worksheet successfully
$this->_parent = null;
@@ -391,9 +390,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
*/
function __destruct() {
- if ($this->_cellCollection !== null) {
- $this->disconnectCells();
- }
+ PHPExcel_Calculation::getInstance($this->_parent)
+ ->clearCalculationCacheForWorksheet($this->_title);
+
+ $this->disconnectCells();
}
/**
@@ -401,8 +401,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @return PHPExcel_CachedObjectStorage_xxx
*/
- public function getCellCacheController()
- {
+ public function getCellCacheController() {
return $this->_cellCollection;
} // function getCellCacheController()
@@ -451,7 +450,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
// Re-order cell collection
return $this->sortCellCollection();
}
- if ($this->_cellCollection !== null) {
+ if ($this->_cellCollection !== NULL) {
return $this->_cellCollection->getCellList();
}
return array();
@@ -464,7 +463,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*/
public function sortCellCollection()
{
- if ($this->_cellCollection !== null) {
+ if ($this->_cellCollection !== NULL) {
return $this->_cellCollection->getSortedCellList();
}
return array();
@@ -709,21 +708,22 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
// loop through all cells in the worksheet
foreach ($this->getCellCollection(false) as $cellID) {
$cell = $this->getCell($cellID);
- if (isset($autoSizes[$cell->getColumn()])) {
+ if (isset($autoSizes[$this->_cellCollection->getCurrentColumn()])) {
// Determine width if cell does not participate in a merge
- if (!isset($isMergeCell[$cell->getCoordinate()])) {
+ if (!isset($isMergeCell[$this->_cellCollection->getCurrentAddress()])) {
// Calculated value
- $cellValue = $cell->getCalculatedValue();
-
// To formatted string
- $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode());
+ $cellValue = PHPExcel_Style_NumberFormat::toFormattedString(
+ $cell->getCalculatedValue(),
+ $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()
+ );
- $autoSizes[$cell->getColumn()] = max(
- (float)$autoSizes[$cell->getColumn()],
+ $autoSizes[$this->_cellCollection->getCurrentColumn()] = max(
+ (float) $autoSizes[$this->_cellCollection->getCurrentColumn()],
(float)PHPExcel_Shared_Font::calculateColumnWidth(
- $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(),
+ $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(),
$cellValue,
- $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(),
+ $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(),
$this->getDefaultStyle()->getFont()
)
);
@@ -746,8 +746,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @return PHPExcel
*/
- public function getParent()
- {
+ public function getParent() {
return $this->_parent;
}
@@ -757,8 +756,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* @param PHPExcel $parent
* @return PHPExcel_Worksheet
*/
- public function rebindParent(PHPExcel $parent)
- {
+ public function rebindParent(PHPExcel $parent) {
$namedRanges = $this->_parent->getNamedRanges();
foreach ($namedRanges as $namedRange) {
$parent->addNamedRange($namedRange);
@@ -791,7 +789,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* This should be left as the default true, unless you are
* certain that no formula cells on any worksheet contain
* references to this worksheet
- *
* @return PHPExcel_Worksheet
*/
public function setTitle($pValue = 'Worksheet', $updateFormulaCellReferences = true)
@@ -807,16 +804,16 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
// Old title
$oldTitle = $this->getTitle();
- if ($this->getParent()) {
+ if ($this->_parent) {
// Is there already such sheet name?
- if ($this->getParent()->sheetNameExists($pValue)) {
+ if ($this->_parent->sheetNameExists($pValue)) {
// Use name, but append with lowest possible integer
if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) {
$pValue = PHPExcel_Shared_String::Substring($pValue,0,29);
}
$i = 1;
- while ($this->getParent()->sheetNameExists($pValue . ' ' . $i)) {
+ while ($this->_parent->sheetNameExists($pValue . ' ' . $i)) {
++$i;
if ($i == 10) {
if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) {
@@ -838,11 +835,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
$this->_title = $pValue;
$this->_dirty = true;
- if ($this->getParent()) {
+ if ($this->_parent) {
// New title
$newTitle = $this->getTitle();
+ PHPExcel_Calculation::getInstance($this->_parent)
+ ->renameCalculationCacheForWorksheet($oldTitle, $newTitle);
if ($updateFormulaCellReferences)
- PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->getParent(), $oldTitle, $newTitle);
+ PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_parent, $oldTitle, $newTitle);
}
return $this;
@@ -853,8 +852,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @return string Sheet state (visible, hidden, veryHidden)
*/
- public function getSheetState()
- {
+ public function getSheetState() {
return $this->_sheetState;
}
@@ -864,8 +862,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* @param string $value Sheet state (visible, hidden, veryHidden)
* @return PHPExcel_Worksheet
*/
- public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE)
- {
+ public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) {
$this->_sheetState = $value;
return $this;
}
@@ -1110,14 +1107,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
// Worksheet reference?
if (strpos($pCoordinate, '!') !== false) {
$worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true);
- return $this->getParent()->getSheetByName($worksheetReference[0])->getCell($worksheetReference[1]);
+ return $this->_parent->getSheetByName($worksheetReference[0])->getCell($worksheetReference[1]);
}
// Named range?
if ((!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 ($namedRange !== null) {
+ if ($namedRange !== NULL) {
$pCoordinate = $namedRange->getRange();
return $namedRange->getWorksheet()->getCell($pCoordinate);
}
@@ -1136,7 +1133,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
// Coordinates
$aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate);
- $cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell($pCoordinate, null, PHPExcel_Cell_DataType::TYPE_NULL, $this));
+ $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]))
@@ -1176,7 +1173,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
$coordinate = $columnLetter . $pRow;
if (!$this->_cellCollection->isDataSet($coordinate)) {
- $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell($coordinate, null, PHPExcel_Cell_DataType::TYPE_NULL, $this));
+ $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)
@@ -1202,14 +1199,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
// Worksheet reference?
if (strpos($pCoordinate, '!') !== false) {
$worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true);
- return $this->getParent()->getSheetByName($worksheetReference[0])->cellExists($worksheetReference[1]);
+ return $this->_parent->getSheetByName($worksheetReference[0])->cellExists($worksheetReference[1]);
}
// Named range?
if ((!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 ($namedRange !== null) {
+ if ($namedRange !== NULL) {
$pCoordinate = $namedRange->getRange();
if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) {
if (!$namedRange->getLocalOnly()) {
@@ -1522,7 +1519,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* Please note that this will overwrite existing cell styles for cells in range!
*
- * @param [PHPExcel_Style_Conditional] $pCellStyle Cell style to duplicate
+ * @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 PHPExcel_Exception
* @return PHPExcel_Worksheet
@@ -1899,7 +1896,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*/
public function removeAutoFilter()
{
- $this->_autoFilter->setRange(null);
+ $this->_autoFilter->setRange(NULL);
return $this;
}
@@ -2179,7 +2176,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
/**
* Set comments array for the entire sheet.
*
- * @param [PHPExcel_Comment] $pValue
+ * @param array of PHPExcel_Comment
* @return PHPExcel_Worksheet
*/
public function setComments($pValue = array())
@@ -2397,10 +2394,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* True - Return rows and columns indexed by their actual row and column IDs
* @return array
*/
- public function rangeToArray(
- $pRange = 'A1', $nullValue = null, $calculateFormulas = true,
- $formatData = true, $returnCellRef = false)
- {
+ public function rangeToArray($pRange = 'A1', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) {
// Returnvalue
$returnValue = array();
// Identify the range that we need to extract from the worksheet
@@ -2445,7 +2439,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
);
}
} else {
- // Cell holds a null
+ // Cell holds a NULL
$returnValue[$rRef][$cRef] = $nullValue;
}
} else {
@@ -2472,20 +2466,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* @return array
* @throws PHPExcel_Exception
*/
- public function namedRangeToArray(
- $pNamedRange = '', $nullValue = null, $calculateFormulas = true,
- $formatData = true, $returnCellRef = false
- )
- {
+ public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) {
$namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this);
- if ($namedRange !== null) {
+ if ($namedRange !== NULL) {
$pWorkSheet = $namedRange->getWorksheet();
$pCellRange = $namedRange->getRange();
- return $pWorkSheet->rangeToArray(
- $pCellRange,
- $nullValue, $calculateFormulas, $formatData, $returnCellRef
- );
+ return $pWorkSheet->rangeToArray( $pCellRange,
+ $nullValue, $calculateFormulas, $formatData, $returnCellRef);
}
throw new PHPExcel_Exception('Named Range '.$pNamedRange.' does not exist.');
@@ -2502,8 +2490,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* True - Return rows and columns indexed by their actual row and column IDs
* @return array
*/
- public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false)
- {
+ public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) {
// Garbage collect...
$this->garbageCollect();
@@ -2511,10 +2498,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
$maxCol = $this->getHighestColumn();
$maxRow = $this->getHighestRow();
// Return
- return $this->rangeToArray(
- 'A1:'.$maxCol.$maxRow,
- $nullValue, $calculateFormulas, $formatData, $returnCellRef
- );
+ return $this->rangeToArray( 'A1:'.$maxCol.$maxRow,
+ $nullValue, $calculateFormulas, $formatData, $returnCellRef);
}
/**
@@ -2523,8 +2508,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* @param integer $startRow The row number at which to start iterating
* @return PHPExcel_Worksheet_RowIterator
*/
- public function getRowIterator($startRow = 1)
- {
+ public function getRowIterator($startRow = 1) {
return new PHPExcel_Worksheet_RowIterator($this,$startRow);
}
@@ -2533,8 +2517,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @return PHPExcel_Worksheet
*/
- public function garbageCollect()
- {
+ public function garbageCollect() {
// Flush cache
$this->_cellCollection->getCacheData('A1');
// Build a reference table from images
@@ -2578,8 +2561,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @return string Hash code
*/
- public function getHashCode()
- {
+ public function getHashCode() {
if ($this->_dirty) {
$this->_hash = md5( $this->_title .
$this->_autoFilter .
@@ -2601,8 +2583,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* @param bool $returnRange Return range? (see example)
* @return mixed
*/
- public static function extractSheetTitle($pRange, $returnRange = false)
- {
+ public static function extractSheetTitle($pRange, $returnRange = false) {
// Sheet title included?
if (($sep = strpos($pRange, '!')) === false) {
return '';
@@ -2733,8 +2714,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
* @param string $range
* @return string Adjusted range value
*/
- public function shrinkRangeToFit($range)
- {
+ public function shrinkRangeToFit($range) {
$maxCol = $this->getHighestColumn();
$maxRow = $this->getHighestRow();
$maxCol = PHPExcel_Cell::columnIndexFromString($maxCol);
@@ -2762,7 +2742,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*/
public function getTabColor()
{
- if ($this->_tabColor === null)
+ if ($this->_tabColor === NULL)
$this->_tabColor = new PHPExcel_Style_Color();
return $this->_tabColor;
@@ -2788,7 +2768,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*/
public function isTabColorSet()
{
- return ($this->_tabColor !== null);
+ return ($this->_tabColor !== NULL);
}
/**
@@ -2796,8 +2776,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
*
* @return PHPExcel_Worksheet
*/
- public function copy()
- {
+ public function copy() {
$copied = clone $this;
return $copied;
@@ -2806,8 +2785,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
- public function __clone()
- {
+ public function __clone() {
foreach ($this as $key => $val) {
if ($key == '_parent') {
continue;
diff --git a/Classes/PHPExcel/Writer/CSV.php b/Classes/PHPExcel/Writer/CSV.php
index 2ff5b410..3563cb23 100644
--- a/Classes/PHPExcel/Writer/CSV.php
+++ b/Classes/PHPExcel/Writer/CSV.php
@@ -102,8 +102,8 @@ class PHPExcel_Writer_CSV extends PHPExcel_Writer_Abstract implements PHPExcel_W
// Fetch sheet
$sheet = $this->_phpExcel->getSheet($this->_sheetIndex);
- $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
- PHPExcel_Calculation::getInstance()->writeDebugLog = false;
+ $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog();
+ PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE);
$saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType();
PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE);
@@ -139,7 +139,7 @@ class PHPExcel_Writer_CSV extends PHPExcel_Writer_Abstract implements PHPExcel_W
fclose($fileHandle);
PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType);
- PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
+ PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog);
}
/**
diff --git a/Classes/PHPExcel/Writer/Excel2007.php b/Classes/PHPExcel/Writer/Excel2007.php
index a74350ca..f09bb271 100644
--- a/Classes/PHPExcel/Writer/Excel2007.php
+++ b/Classes/PHPExcel/Writer/Excel2007.php
@@ -179,8 +179,8 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE
}
}
- $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
- PHPExcel_Calculation::getInstance()->writeDebugLog = false;
+ $saveDebugLog = PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->getWriteDebugLog();
+ PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog(FALSE);
$saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType();
PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL);
@@ -341,7 +341,7 @@ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPE
}
PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType);
- PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
+ PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
// Close file
if ($objZip->close() === false) {
diff --git a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php
index 977f172d..cb1437d3 100644
--- a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php
+++ b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php
@@ -1074,12 +1074,9 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ
$objWriter->writeAttribute('t', $mappedType);
break;
case 'f': // Formula
- $calculatedValue = null;
- if ($this->getParentWriter()->getPreCalculateFormulas()) {
- $calculatedValue = $pCell->getCalculatedValue();
- } else {
- $calculatedValue = $cellValue;
- }
+ $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ?
+ $pCell->getCalculatedValue() :
+ $cellValue;
if (is_string($calculatedValue)) {
$objWriter->writeAttribute('t', 'str');
}
@@ -1125,7 +1122,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ
}
if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
if ($this->getParentWriter()->getPreCalculateFormulas()) {
- $calculatedValue = $pCell->getCalculatedValue();
+// $calculatedValue = $pCell->getCalculatedValue();
if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') {
$objWriter->writeElement('v', PHPExcel_Shared_String::FormatNumber($calculatedValue));
} else {
diff --git a/Classes/PHPExcel/Writer/Excel5.php b/Classes/PHPExcel/Writer/Excel5.php
index 459653c6..a63c1d1c 100644
--- a/Classes/PHPExcel/Writer/Excel5.php
+++ b/Classes/PHPExcel/Writer/Excel5.php
@@ -120,8 +120,8 @@ class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExce
// garbage collect
$this->_phpExcel->garbageCollect();
- $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
- PHPExcel_Calculation::getInstance()->writeDebugLog = false;
+ $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog();
+ PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE);
$saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType();
PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL);
@@ -226,7 +226,7 @@ class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExce
$res = $root->save($pFilename);
PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType);
- PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
+ PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog);
}
/**
diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php
index fb467f36..a30033f1 100644
--- a/Classes/PHPExcel/Writer/HTML.php
+++ b/Classes/PHPExcel/Writer/HTML.php
@@ -152,8 +152,8 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_
// garbage collect
$this->_phpExcel->garbageCollect();
- $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog;
- PHPExcel_Calculation::getInstance()->writeDebugLog = false;
+ $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog();
+ PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE);
$saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType();
PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE);
@@ -184,7 +184,7 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_
fclose($fileHandle);
PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType);
- PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog;
+ PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog);
}
/**
diff --git a/Examples/06largescale-with-cellcaching-sqlite.php b/Examples/06largescale-with-cellcaching-sqlite.php
new file mode 100644
index 00000000..fff36959
--- /dev/null
+++ b/Examples/06largescale-with-cellcaching-sqlite.php
@@ -0,0 +1,126 @@
+');
+
+date_default_timezone_set('Europe/London');
+
+/** Include PHPExcel */
+require_once '../Classes/PHPExcel.php';
+
+$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_sqlite;
+PHPExcel_Settings::setCacheStorageMethod($cacheMethod);
+echo date('H:i:s') , " Enable Cell Caching using " , $cacheMethod , " method" , EOL;
+
+
+// Create new PHPExcel object
+echo date('H:i:s') , " Create new PHPExcel object" , EOL;
+$objPHPExcel = new PHPExcel();
+
+// Set document properties
+echo date('H:i:s') , " Set properties" , EOL;
+$objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
+ ->setLastModifiedBy("Maarten Balliauw")
+ ->setTitle("Office 2007 XLSX Test Document")
+ ->setSubject("Office 2007 XLSX Test Document")
+ ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
+ ->setKeywords("office 2007 openxml php")
+ ->setCategory("Test result file");
+
+
+// Create a first sheet
+echo date('H:i:s') , " Add data" , EOL;
+$objPHPExcel->setActiveSheetIndex(0);
+$objPHPExcel->getActiveSheet()->setCellValue('A1', "Firstname");
+$objPHPExcel->getActiveSheet()->setCellValue('B1', "Lastname");
+$objPHPExcel->getActiveSheet()->setCellValue('C1', "Phone");
+$objPHPExcel->getActiveSheet()->setCellValue('D1', "Fax");
+$objPHPExcel->getActiveSheet()->setCellValue('E1', "Is Client ?");
+
+
+// Hide "Phone" and "fax" column
+echo date('H:i:s') , " Hide 'Phone' and 'fax' columns" , EOL;
+$objPHPExcel->getActiveSheet()->getColumnDimension('C')->setVisible(false);
+$objPHPExcel->getActiveSheet()->getColumnDimension('D')->setVisible(false);
+
+
+// Set outline levels
+echo date('H:i:s') , " Set outline levels" , EOL;
+$objPHPExcel->getActiveSheet()->getColumnDimension('E')->setOutlineLevel(1)
+ ->setVisible(false)
+ ->setCollapsed(true);
+
+// Freeze panes
+echo date('H:i:s') , " Freeze panes" , EOL;
+$objPHPExcel->getActiveSheet()->freezePane('A2');
+
+
+// Rows to repeat at top
+echo date('H:i:s') , " Rows to repeat at top" , EOL;
+$objPHPExcel->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEnd(1, 1);
+
+
+// Add data
+for ($i = 2; $i <= 5000; $i++) {
+ $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, "FName $i")
+ ->setCellValue('B' . $i, "LName $i")
+ ->setCellValue('C' . $i, "PhoneNo $i")
+ ->setCellValue('D' . $i, "FaxNo $i")
+ ->setCellValue('E' . $i, true);
+}
+
+
+// Set active sheet index to the first sheet, so Excel opens this as the first sheet
+$objPHPExcel->setActiveSheetIndex(0);
+
+
+// Save Excel 2007 file
+echo date('H:i:s') , " Write to Excel2007 format" , EOL;
+$callStartTime = microtime(true);
+
+$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
+$objWriter->save(str_replace('.php', '.xlsx', __FILE__));
+$callEndTime = microtime(true);
+$callTime = $callEndTime - $callStartTime;
+
+echo date('H:i:s') , " File written to " , str_replace('.php', '.xlsx', pathinfo(__FILE__, PATHINFO_BASENAME)) , EOL;
+echo 'Call time to write Workbook was ' , sprintf('%.4f',$callTime) , " seconds" , EOL;
+// Echo memory usage
+echo date('H:i:s') , ' Current memory usage: ' , (memory_get_usage(true) / 1024 / 1024) , " MB" , EOL;
+
+
+// Echo memory peak usage
+echo date('H:i:s') , " Peak memory usage: " , (memory_get_peak_usage(true) / 1024 / 1024) , " MB" , EOL;
+
+// Echo done
+echo date('H:i:s') , " Done writing file" , EOL;
+echo 'File has been created in ' , getcwd() , EOL;
diff --git a/Examples/06largescale-with-cellcaching-sqlite3.php b/Examples/06largescale-with-cellcaching-sqlite3.php
new file mode 100644
index 00000000..a4c537a5
--- /dev/null
+++ b/Examples/06largescale-with-cellcaching-sqlite3.php
@@ -0,0 +1,126 @@
+');
+
+date_default_timezone_set('Europe/London');
+
+/** Include PHPExcel */
+require_once '../Classes/PHPExcel.php';
+
+$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_sqlite3;
+PHPExcel_Settings::setCacheStorageMethod($cacheMethod);
+echo date('H:i:s') , " Enable Cell Caching using " , $cacheMethod , " method" , EOL;
+
+
+// Create new PHPExcel object
+echo date('H:i:s') , " Create new PHPExcel object" , EOL;
+$objPHPExcel = new PHPExcel();
+
+// Set document properties
+echo date('H:i:s') , " Set properties" , EOL;
+$objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
+ ->setLastModifiedBy("Maarten Balliauw")
+ ->setTitle("Office 2007 XLSX Test Document")
+ ->setSubject("Office 2007 XLSX Test Document")
+ ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
+ ->setKeywords("office 2007 openxml php")
+ ->setCategory("Test result file");
+
+
+// Create a first sheet
+echo date('H:i:s') , " Add data" , EOL;
+$objPHPExcel->setActiveSheetIndex(0);
+$objPHPExcel->getActiveSheet()->setCellValue('A1', "Firstname");
+$objPHPExcel->getActiveSheet()->setCellValue('B1', "Lastname");
+$objPHPExcel->getActiveSheet()->setCellValue('C1', "Phone");
+$objPHPExcel->getActiveSheet()->setCellValue('D1', "Fax");
+$objPHPExcel->getActiveSheet()->setCellValue('E1', "Is Client ?");
+
+
+// Hide "Phone" and "fax" column
+echo date('H:i:s') , " Hide 'Phone' and 'fax' columns" , EOL;
+$objPHPExcel->getActiveSheet()->getColumnDimension('C')->setVisible(false);
+$objPHPExcel->getActiveSheet()->getColumnDimension('D')->setVisible(false);
+
+
+// Set outline levels
+echo date('H:i:s') , " Set outline levels" , EOL;
+$objPHPExcel->getActiveSheet()->getColumnDimension('E')->setOutlineLevel(1)
+ ->setVisible(false)
+ ->setCollapsed(true);
+
+// Freeze panes
+echo date('H:i:s') , " Freeze panes" , EOL;
+$objPHPExcel->getActiveSheet()->freezePane('A2');
+
+
+// Rows to repeat at top
+echo date('H:i:s') , " Rows to repeat at top" , EOL;
+$objPHPExcel->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEnd(1, 1);
+
+
+// Add data
+for ($i = 2; $i <= 5000; $i++) {
+ $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, "FName $i")
+ ->setCellValue('B' . $i, "LName $i")
+ ->setCellValue('C' . $i, "PhoneNo $i")
+ ->setCellValue('D' . $i, "FaxNo $i")
+ ->setCellValue('E' . $i, true);
+}
+
+
+// Set active sheet index to the first sheet, so Excel opens this as the first sheet
+$objPHPExcel->setActiveSheetIndex(0);
+
+
+// Save Excel 2007 file
+echo date('H:i:s') , " Write to Excel2007 format" , EOL;
+$callStartTime = microtime(true);
+
+$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
+$objWriter->save(str_replace('.php', '.xlsx', __FILE__));
+$callEndTime = microtime(true);
+$callTime = $callEndTime - $callStartTime;
+
+echo date('H:i:s') , " File written to " , str_replace('.php', '.xlsx', pathinfo(__FILE__, PATHINFO_BASENAME)) , EOL;
+echo 'Call time to write Workbook was ' , sprintf('%.4f',$callTime) , " seconds" , EOL;
+// Echo memory usage
+echo date('H:i:s') , ' Current memory usage: ' , (memory_get_usage(true) / 1024 / 1024) , " MB" , EOL;
+
+
+// Echo memory peak usage
+echo date('H:i:s') , " Peak memory usage: " , (memory_get_peak_usage(true) / 1024 / 1024) , " MB" , EOL;
+
+// Echo done
+echo date('H:i:s') , " Done writing file" , EOL;
+echo 'File has been created in ' , getcwd() , EOL;
diff --git a/changelog.txt b/changelog.txt
index 600a33fd..27410f85 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -23,7 +23,7 @@
**************************************************************************************
-Fixed in develop branch:
+Fixed in develop branch for release v1.7.9:
- Feature: (MBaker) Include charts option for HTML Writer
- Feature: (MBaker) Added composer file
- Bugfix: (Asker) Work item 18777 - Error in PHPEXCEL/Calculation.php script on line 2976 (stack pop check)
@@ -41,6 +41,8 @@ Fixed in develop branch:
- General: (cfhay) Work item 18958 - Memory and Speed improvements in PHPExcel_Reader_Excel5
- General: (MBaker) Work item GH-78 - Modify listWorksheetNames() and listWorksheetInfo to use XMLReader with streamed XML rather than SimpleXML
- General: (dbonsch) Restructuring of PHPExcel Exceptions
+- General: (MBaker) Work items 16926 and 15145 - Refactor Calculation Engine from singleton to a Multiton
+ Ensures that calculation cache is maintained independently for different workbooks
- Bugfix: (techhead) Work item GH-70 - Fixed formula/formatting bug when removing rows
- Bugfix: (alexgann) Work item GH-63 - Fix to cellExists for non-existent namedRanges
- Bugfix: (MBaker) Work item 18844 - cache_in_memory_gzip "eats" last worksheet line, cache_in_memory doesn't
@@ -52,6 +54,7 @@ Fixed in develop branch:
- Bugfix: (MBaker) Work item GH-113 - canRead() Error for GoogleDocs ODS files: in ODS files from Google Docs there is no mimetype file
- Bugfix: (MBaker) Work item GH-80 - "Sheet index is out of bounds." Exception
- Bugfix: (ccorliss) Work item GH-105 - Fixed number format fatal error
+- Bugfix: (MBaker) - Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers
--------------------------------------------------------------------------------
BREAKING CHANGE! As part of the planned changes for handling array formulae in
diff --git a/unitTests/Classes/PHPExcel/Cell/AdvancedValueBinderTest.php b/unitTests/Classes/PHPExcel/Cell/AdvancedValueBinderTest.php
index a76a2b25..0a6ca54d 100644
--- a/unitTests/Classes/PHPExcel/Cell/AdvancedValueBinderTest.php
+++ b/unitTests/Classes/PHPExcel/Cell/AdvancedValueBinderTest.php
@@ -35,7 +35,16 @@ class AdvancedValueBinderTest extends PHPUnit_Framework_TestCase
*/
public function testCurrency($value, $valueBinded, $format, $thousandsSeparator, $decimalSeparator, $currencyCode)
{
- $sheet = $this->getMock('PHPExcel_Worksheet', array('getStyle', 'getNumberFormat', 'setFormatCode'));
+ $sheet = $this->getMock(
+ 'PHPExcel_Worksheet',
+ array('getStyle', 'getNumberFormat', 'setFormatCode','getCellCacheController')
+ );
+ $cache = $this->getMockBuilder('PHPExcel_CachedObjectStorage_Memory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $cache->expects($this->any())
+ ->method('getParent')
+ ->will($this->returnValue($sheet));
$sheet->expects($this->once())
->method('getStyle')
@@ -47,12 +56,15 @@ class AdvancedValueBinderTest extends PHPUnit_Framework_TestCase
->method('setFormatCode')
->with($format)
->will($this->returnSelf());
+ $sheet->expects($this->any())
+ ->method('getCellCacheController')
+ ->will($this->returnValue($cache));
PHPExcel_Shared_String::setCurrencyCode($currencyCode);
PHPExcel_Shared_String::setDecimalSeparator($decimalSeparator);
PHPExcel_Shared_String::setThousandsSeparator($thousandsSeparator);
- $cell = new PHPExcel_Cell('A', 1, null, PHPExcel_Cell_DataType::TYPE_STRING, $sheet);
+ $cell = new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_STRING, $sheet);
$binder = new PHPExcel_Cell_AdvancedValueBinder();
$binder->bindValue($cell, $value);
diff --git a/unitTests/Classes/PHPExcel/Worksheet/AutoFilterTest.php b/unitTests/Classes/PHPExcel/Worksheet/AutoFilterTest.php
index 6a6d5ae8..9907eabc 100644
--- a/unitTests/Classes/PHPExcel/Worksheet/AutoFilterTest.php
+++ b/unitTests/Classes/PHPExcel/Worksheet/AutoFilterTest.php
@@ -18,6 +18,12 @@ class AutoFilterTest extends PHPUnit_Framework_TestCase
$this->_mockWorksheetObject = $this->getMockBuilder('PHPExcel_Worksheet')
->disableOriginalConstructor()
->getMock();
+ $this->_mockCacheController = $this->getMockBuilder('PHPExcel_CachedObjectStorage_Memory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->_mockWorksheetObject->expects($this->any())
+ ->method('getCellCacheController')
+ ->will($this->returnValue($this->_mockCacheController));
$this->_testAutoFilterObject = new PHPExcel_Worksheet_AutoFilter(
$this->_testInitialRange,
diff --git a/unitTests/rawTestData/Calculation/DateTime/DATEVALUE.data b/unitTests/rawTestData/Calculation/DateTime/DATEVALUE.data
index 281c707f..43970c28 100644
--- a/unitTests/rawTestData/Calculation/DateTime/DATEVALUE.data
+++ b/unitTests/rawTestData/Calculation/DateTime/DATEVALUE.data
@@ -35,11 +35,11 @@
"22 August 98", 36029
"1st March 2007", 39142 // MS Excel will fail with a #VALUE return, but PHPExcel can parse this date
"The 1st day of March 2007", "#VALUE!"
-"1 Jan", 40909
-"31/12", 41274
+"1 Jan", 41275
+"31/12", 41639
"12/31", 11658 // Excel reads as 1st December 1931, not 31st December in current year
-"5-JUL", 41095
-"5 Jul", 41095
+"5-JUL", 41460
+"5 Jul", 41460
"12/2008", 39783
"10/32", 11963
11, "#VALUE!"