From 1e1a6ac3613d6fb7661fbceb0e3c62cb3c8090e0 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 4 Feb 2013 17:26:27 +0000 Subject: [PATCH 01/45] Convert singleton calculation engine to multiton --- Classes/PHPExcel.php | 43 ++++++++++++++++++-- Classes/PHPExcel/Calculation.php | 70 ++++++++++++++++++++++++-------- Classes/PHPExcel/Cell.php | 8 ++-- 3 files changed, 96 insertions(+), 25 deletions(-) diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php index ec98ad03..901cb16d 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); @@ -127,6 +144,14 @@ class PHPExcel } + /** + * Destroy this workbook + */ + public function __destruct() { + PHPExcel_Calculation::unsetInstance($this); + $this->disconnectWorksheets(); + } // function __destruct() + /** * Disconnect all worksheets from this PHPExcel workbook object, * typically so that the PHPExcel object can be unset @@ -141,6 +166,16 @@ class PHPExcel $this->_workSheetCollection = array(); } + /** + * Return the calculation engine for this worksheet + * + * @return PHPExcel_Calculation + */ + public function getCalculationEngine() { + + return $this->_calculationEngine; + } // function getCellCacheController() + /** * Get properties * @@ -824,12 +859,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/Calculation.php b/Classes/PHPExcel/Calculation.php index 254a4e9c..a2f53721 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; /** @@ -1671,12 +1687,18 @@ class PHPExcel_Calculation { - private function __construct() { + private function __construct(PHPExcel $workbook = NULL) { $setPrecision = (PHP_INT_SIZE == 4) ? 12 : 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; } // function __construct() @@ -1702,7 +1724,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 +1739,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,10 +1754,8 @@ 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() @@ -1792,7 +1826,7 @@ class PHPExcel_Calculation { * @return boolean */ public function getCalculationCacheEnabled() { - return self::$_calculationCacheEnabled; + return $this->_calculationCacheEnabled; } // function getCalculationCacheEnabled() @@ -1803,7 +1837,7 @@ class PHPExcel_Calculation { * @param boolean $pValue */ public function setCalculationCacheEnabled($pValue = true) { - self::$_calculationCacheEnabled = $pValue; + $this->_calculationCacheEnabled = $pValue; $this->clearCalculationCache(); } // function setCalculationCacheEnabled() @@ -1828,7 +1862,7 @@ class PHPExcel_Calculation { * Clear calculation cache */ public function clearCalculationCache() { - self::$_calculationCache = array(); + $this->_calculationCache = array(); } // function clearCalculationCache() @@ -2206,7 +2240,7 @@ class PHPExcel_Calculation { // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache $resetCache = $this->getCalculationCacheEnabled(); - self::$_calculationCacheEnabled = false; + $this->_calculationCacheEnabled = FALSE; // Execute the calculation try { $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); @@ -2215,7 +2249,7 @@ class PHPExcel_Calculation { } // Reset calculation cacheing to its previous state - self::$_calculationCacheEnabled = $resetCache; + $this->_calculationCacheEnabled = $resetCache; return $result; } // function calculateFormula() @@ -2250,15 +2284,15 @@ class PHPExcel_Calculation { } // Is calculation cacheing enabled? if ($cellID !== NULL) { - if (self::$_calculationCacheEnabled) { + if ($this->_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])) { + if (isset($this->_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]; + $returnValue = $this->_calculationCache[$wsTitle][$cellID]; // echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
'; if (is_array($returnValue)) { $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue); @@ -2294,8 +2328,8 @@ class PHPExcel_Calculation { // Save to calculation cache if ($cellID !== NULL) { - if (self::$_calculationCacheEnabled) { - self::$_calculationCache[$wsTitle][$cellID] = $cellValue; + if ($this->_calculationCacheEnabled) { + $this->_calculationCache[$wsTitle][$cellID] = $cellValue; } } diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php index 2e9cd327..ea37c7ec 100644 --- a/Classes/PHPExcel/Cell.php +++ b/Classes/PHPExcel/Cell.php @@ -288,7 +288,7 @@ class PHPExcel_Cell 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); + $result = $this->getParent()->getParent()->getCalculationEngine()->calculateCellValue($this,$resetLog); // echo $this->getCoordinate().' calculation result is '.$result.'
'; } catch ( PHPExcel_Exception $ex ) { if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) { @@ -859,11 +859,11 @@ class PHPExcel_Cell */ public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b) { - 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; From 6f4cfcc8c6331e80dc3b9e2ea23ea1a25518cb43 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 4 Feb 2013 23:16:39 +0000 Subject: [PATCH 02/45] Ensure that writers access the workbook rather than the global calculation engine --- Classes/PHPExcel/Writer/CSV.php | 6 +++--- Classes/PHPExcel/Writer/Excel2007.php | 6 +++--- Classes/PHPExcel/Writer/Excel5.php | 8 ++++---- Classes/PHPExcel/Writer/HTML.php | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Classes/PHPExcel/Writer/CSV.php b/Classes/PHPExcel/Writer/CSV.php index 2ff5b410..3979d609 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)->writeDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->writeDebugLog = 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)->writeDebugLog = $saveDebugLog; } /** diff --git a/Classes/PHPExcel/Writer/Excel2007.php b/Classes/PHPExcel/Writer/Excel2007.php index a74350ca..951b3397 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)->writeDebugLog; + PHPExcel_Calculation::getInstance($this->_spreadSheet)->writeDebugLog = 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)->writeDebugLog = $saveDebugLog; // Close file if ($objZip->close() === false) { diff --git a/Classes/PHPExcel/Writer/Excel5.php b/Classes/PHPExcel/Writer/Excel5.php index 459653c6..daa1d0fe 100644 --- a/Classes/PHPExcel/Writer/Excel5.php +++ b/Classes/PHPExcel/Writer/Excel5.php @@ -120,13 +120,13 @@ 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)->writeDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->writeDebugLog = false; $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); // initialize colors array - $this->_colors = array(); + $this->_colors = array(); // Initialise workbook writer $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, @@ -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)->writeDebugLog = $saveDebugLog; } /** diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index d07dbd2d..5aca92e9 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)->writeDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->writeDebugLog = 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)->writeDebugLog = $saveDebugLog; } /** From abb076a8175d4c39113210098ec8e4d39b334974 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Tue, 5 Feb 2013 09:52:28 +0000 Subject: [PATCH 03/45] Use direct reference to workbook in Calc Engine rather than cell's parent's parent --- Classes/PHPExcel/Calculation.php | 36 +++++++++++++------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index a2f53721..0e4f066c 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -1829,7 +1829,6 @@ class PHPExcel_Calculation { return $this->_calculationCacheEnabled; } // function getCalculationCacheEnabled() - /** * Enable/disable calculation cache * @@ -2265,7 +2264,7 @@ class PHPExcel_Calculation { * @throws PHPExcel_Calculation_Exception */ public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) { -// echo ''.$cellID.'
'; +//echo $cellID,PHP_EOL; $cellValue = ''; // Basic validation that this is indeed a formula @@ -2275,25 +2274,20 @@ class PHPExcel_Calculation { $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(); - } - } + $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : NULL; + $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk"; // Is calculation cacheing enabled? if ($cellID !== NULL) { if ($this->_calculationCacheEnabled) { // Is the value present in calculation cache? $this->_writeDebug('Testing cache value for cell ', $cellID); -// echo 'Testing cache value
'; +//echo 'Testing cache value',PHP_EOL; if (isset($this->_calculationCache[$wsTitle][$cellID])) { -// echo 'Value is in cache
'; +//echo 'Value is in cache',PHP_EOL; $this->_writeDebug('Retrieving value for ', $cellID, ' from cache'); // Return the cached result $returnValue = $this->_calculationCache[$wsTitle][$cellID]; -// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
'; +//echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache',PHP_EOL; if (is_array($returnValue)) { $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue); return array_shift($returnValue); @@ -2670,9 +2664,9 @@ class PHPExcel_Calculation { // 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).'
'; +//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.'
'; +//echo 'Initial character of expression block is '.$opCharacter,PHP_EOL; if ((isset($comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset($comparisonOperators[$formula{$index+1}]))) { $opCharacter .= $formula{++$index}; // echo 'Initial character of expression block is comparison operator '.$opCharacter.'
'; @@ -3004,7 +2998,7 @@ class PHPExcel_Calculation { // 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; + $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : NULL; $stack = new PHPExcel_Calculation_Token_Stack; // Loop through each token in turn @@ -3083,7 +3077,7 @@ 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'); } @@ -3203,7 +3197,7 @@ class PHPExcel_Calculation { // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; $this->_writeDebug('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'); } @@ -3236,8 +3230,8 @@ class PHPExcel_Calculation { // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; $this->_writeDebug('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; @@ -3618,7 +3612,7 @@ class PHPExcel_Calculation { if (strpos ($pRange, '!') !== false) { // echo '$pRange reference includes sheet reference
'; $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true); - $pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]); + $pSheet = $this->_workbook->getSheetByName($worksheetReference[0]); // echo 'New sheet name is '.$pSheet->getTitle().'
'; $pRange = $worksheetReference[1]; // echo 'Adjusted Range reference is '.$pRange.'
'; @@ -3674,7 +3668,7 @@ class PHPExcel_Calculation { if (strpos ($pRange, '!') !== false) { // echo '$pRange reference includes sheet reference
'; $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true); - $pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]); + $pSheet = $this->_workbook->getSheetByName($worksheetReference[0]); // echo 'New sheet name is '.$pSheet->getTitle().'
'; $pRange = $worksheetReference[1]; // echo 'Adjusted Range reference is '.$pRange.'
'; From f05f66fa82802ef457a4862a9ae87bd5615be646 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 11 Feb 2013 14:11:36 +0000 Subject: [PATCH 04/45] Eliminate some code duplication --- Classes/PHPExcel/Calculation.php | 440 ++++++++++---------- Classes/PHPExcel/Cell.php | 5 +- Classes/PHPExcel/Chart/DataSeriesValues.php | 2 +- 3 files changed, 227 insertions(+), 220 deletions(-) diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index 0e4f066c..e04fd695 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -127,7 +127,7 @@ class PHPExcel_Calculation { * @access private * @var boolean */ - private $_calculationCacheEnabled = true; + private $_calculationCacheEnabled = TRUE; /** @@ -137,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 ); @@ -150,10 +150,10 @@ 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 ); /** @@ -165,7 +165,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 @@ -174,7 +174,7 @@ class PHPExcel_Calculation { * @var string * */ - public $formulaError = null; + public $formulaError = NULL; /** * Flag to determine whether a debug log should be generated by the calculation engine @@ -185,7 +185,7 @@ class PHPExcel_Calculation { * @var boolean * */ - public $writeDebugLog = false; + public $writeDebugLog = FALSE; /** * Flag to determine whether a debug log should be echoed by the calculation engine @@ -197,7 +197,7 @@ class PHPExcel_Calculation { * @var boolean * */ - public $echoDebugLog = false; + public $echoDebugLog = FALSE; /** @@ -237,9 +237,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 @@ -411,7 +411,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', @@ -820,7 +820,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', @@ -909,7 +909,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', @@ -1226,8 +1226,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', @@ -1372,7 +1372,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', @@ -1766,7 +1766,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() @@ -1802,10 +1802,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() /** @@ -1816,7 +1816,7 @@ class PHPExcel_Calculation { */ public static function getArrayReturnType() { return self::$returnArrayAsType; - } // function getExcelCalendar() + } // function getArrayReturnType() /** @@ -1835,7 +1835,7 @@ class PHPExcel_Calculation { * @access public * @param boolean $pValue */ - public function setCalculationCacheEnabled($pValue = true) { + public function setCalculationCacheEnabled($pValue = TRUE) { $this->_calculationCacheEnabled = $pValue; $this->clearCalculationCache(); } // function setCalculationCacheEnabled() @@ -1845,7 +1845,7 @@ class PHPExcel_Calculation { * Enable calculation cache */ public function enableCalculationCache() { - $this->setCalculationCacheEnabled(true); + $this->setCalculationCacheEnabled(TRUE); } // function enableCalculationCache() @@ -1853,7 +1853,7 @@ class PHPExcel_Calculation { * Disable calculation cache */ public function disableCalculationCache() { - $this->setCalculationCacheEnabled(false); + $this->setCalculationCacheEnabled(FALSE); } // function disableCalculationCache() @@ -1883,7 +1883,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); } @@ -1904,14 +1904,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); @@ -1932,7 +1932,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) { @@ -1946,11 +1946,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() @@ -1960,9 +1960,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) { @@ -1976,13 +1976,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) { @@ -2003,8 +2003,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) { @@ -2032,8 +2032,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) { @@ -2129,7 +2129,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) { @@ -2147,24 +2147,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) { + // Initialise the logging settings if requested + $this->formulaError = NULL; + $this->debugLog = $this->debugLogStack = array(); + $this->_cyclicFormulaCount = 1; + + self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; + } + if ($resetLog) { - self::$returnArrayAsType = $returnArrayAsType; } // Execute the calculation for the cell formula try { @@ -2174,6 +2172,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(); @@ -2194,6 +2193,8 @@ class PHPExcel_Calculation { } $result = array_shift($testResult); } + self::$returnArrayAsType = $returnArrayAsType; + if ($result === NULL) { return 0; @@ -2231,7 +2232,7 @@ 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(); @@ -2254,6 +2255,25 @@ class PHPExcel_Calculation { } // function calculateFormula() + public function getValueFromCache($worksheetName, $cellID, &$cellValue) { + // Is calculation cacheing enabled? + // Is the value present in calculation cache? + $this->_writeDebug('Testing cache value for cell ', $worksheetName, '!', $cellID); + if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$worksheetName][$cellID]))) { + $this->_writeDebug('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 * @@ -2264,11 +2284,10 @@ class PHPExcel_Calculation { * @throws PHPExcel_Calculation_Exception */ public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) { -//echo $cellID,PHP_EOL; $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)); @@ -2276,28 +2295,12 @@ class PHPExcel_Calculation { $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : NULL; $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk"; - // Is calculation cacheing enabled? - if ($cellID !== NULL) { - if ($this->_calculationCacheEnabled) { - // Is the value present in calculation cache? - $this->_writeDebug('Testing cache value for cell ', $cellID); -//echo 'Testing cache value',PHP_EOL; - if (isset($this->_calculationCache[$wsTitle][$cellID])) { -//echo 'Value is in cache',PHP_EOL; - $this->_writeDebug('Retrieving value for ', $cellID, ' from cache'); - // Return the cached result - $returnValue = $this->_calculationCache[$wsTitle][$cellID]; -//echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache',PHP_EOL; - if (is_array($returnValue)) { - $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue); - return array_shift($returnValue); - } - return $returnValue; - } - } + + if (($cellID !== NULL) && ($this->getValueFromCache($wsTitle, $cellID, $cellValue))) { + return $cellValue; } - if ((in_array($wsTitle.'!'.$cellID,$this->debugLogStack)) && ($wsTitle != "\x00Wrk")) { + if (($wsTitle{0} !== "\x00") && (in_array($wsTitle.'!'.$cellID,$this->debugLogStack))) { if ($this->cyclicFormulaCount <= 0) { return $this->_raiseFormulaError('Cyclic Reference in Formula'); } elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) && @@ -2322,9 +2325,7 @@ class PHPExcel_Calculation { // Save to calculation cache if ($cellID !== NULL) { - if ($this->_calculationCacheEnabled) { - $this->_calculationCache[$wsTitle][$cellID] = $cellValue; - } + $this->saveValueToCache($wsTitle, $cellID, $cellValue); } // Return the calculated value @@ -2555,15 +2556,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) { @@ -2606,9 +2607,40 @@ 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; } @@ -2616,34 +2648,6 @@ class PHPExcel_Calculation { // 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 - ); - $regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION. '|'.self::CALCULATION_REGEXP_NUMBER. '|'.self::CALCULATION_REGEXP_STRING. @@ -2657,55 +2661,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) { + 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,PHP_EOL; - if ((isset($comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset($comparisonOperators[$formula{$index+1}]))) { + 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; @@ -2713,65 +2717,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; @@ -2784,7 +2788,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 @@ -2792,7 +2796,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); @@ -2801,8 +2805,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) { @@ -2811,8 +2815,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
'; @@ -2825,14 +2829,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
'; @@ -2857,7 +2861,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 @@ -2865,12 +2869,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 .= '!'; @@ -2889,14 +2893,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 { @@ -2907,11 +2911,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; } @@ -2921,9 +2925,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 ')'"); } @@ -2959,11 +2963,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; } } } @@ -2993,8 +2997,8 @@ 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 @@ -3038,12 +3042,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() : ''; } - if (strpos($operand2Data['reference'],'!') !== false) { + if (strpos($operand2Data['reference'],'!') !== FALSE) { list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); } else { $sheet2 = $sheet1; @@ -3077,13 +3081,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, $this->_workbook->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; @@ -3178,7 +3182,7 @@ class PHPExcel_Calculation { } } 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
'; @@ -3189,7 +3193,7 @@ 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'); } @@ -3197,7 +3201,7 @@ class PHPExcel_Calculation { // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; $this->_writeDebug('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { - $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), false); + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } @@ -3207,7 +3211,7 @@ class PHPExcel_Calculation { // echo '$cellRef='.$cellRef.' in current worksheet
'; $this->_writeDebug('Evaluating Cell Range ', $cellRef, ' in current worksheet'); if ($pCellParent !== NULL) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent, false); + $cellValue = $this->extractCellRange($cellRef, $pCellParent, FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } @@ -3223,7 +3227,7 @@ 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'); } @@ -3231,10 +3235,10 @@ class PHPExcel_Calculation { $this->_writeDebug('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { if ($this->_workbook->getSheetByName($matches[2])->cellExists($cellRef)) { - $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), false); + $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'); @@ -3245,10 +3249,10 @@ class PHPExcel_Calculation { // echo '$cellRef='.$cellRef.' in current worksheet
'; $this->_writeDebug('Evaluating Cell ', $cellRef, ' in current worksheet'); if ($pCellParent->cellExists($cellRef)) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent, false); + $cellValue = $this->extractCellRange($cellRef, $pCellParent, FALSE); $pCell->attach($pCellParent); } else { - $cellValue = null; + $cellValue = NULL; } $this->_writeDebug('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } @@ -3338,7 +3342,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) { @@ -3370,7 +3374,7 @@ class PHPExcel_Calculation { $namedRange = $matches[6]; // echo 'Named Range is '.$namedRange.'
'; $this->_writeDebug('Evaluating Named Range ', $namedRange); - $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCellParent : null), false); + $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellParent : NULL), FALSE); $pCell->attach($pCellParent); $this->_writeDebug('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue)); $stack->push('Named Range',$cellValue,$namedRange); @@ -3391,7 +3395,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 @@ -3403,22 +3407,22 @@ class PHPExcel_Calculation { if ($operand > '' && $operand{0} == '#') { $stack->push('Value', $operand); $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($operand)); - return false; + 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; + 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(); @@ -3440,7 +3444,7 @@ class PHPExcel_Calculation { 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->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,TRUE); $r = $stack->pop(); $result[$x] = $r['value']; } @@ -3449,7 +3453,7 @@ class PHPExcel_Calculation { $this->_writeDebug('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 @@ -3488,28 +3492,28 @@ class PHPExcel_Calculation { $this->_writeDebug('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]; } @@ -3551,7 +3555,7 @@ class PHPExcel_Calculation { // Trap for Divide by Zero error $stack->push('Value','#DIV/0!'); $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!')); - return false; + return FALSE; } else { $result = $operand1/$operand2; } @@ -3568,7 +3572,7 @@ class PHPExcel_Calculation { $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Value',$result); - return true; + return TRUE; } // function _executeNumericBinaryOperation() @@ -3601,7 +3605,7 @@ 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 (); @@ -3609,9 +3613,9 @@ class PHPExcel_Calculation { if ($pSheet !== NULL) { // echo 'Passed sheet name is '.$pSheet->getTitle().'
'; // echo 'Range reference is '.$pRange.'
'; - if (strpos ($pRange, '!') !== false) { + if (strpos ($pRange, '!') !== FALSE) { // echo '$pRange reference includes sheet reference
'; - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true); + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, TRUE); $pSheet = $this->_workbook->getSheetByName($worksheetReference[0]); // echo 'New sheet name is '.$pSheet->getTitle().'
'; $pRange = $worksheetReference[1]; @@ -3627,7 +3631,7 @@ class PHPExcel_Calculation { 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 @@ -3638,7 +3642,7 @@ class PHPExcel_Calculation { if ($pSheet->cellExists($reference)) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); } else { - $returnValue[$currentRow][$currentCol] = null; + $returnValue[$currentRow][$currentCol] = NULL; } } } @@ -3657,7 +3661,7 @@ 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 (); @@ -3665,9 +3669,9 @@ class PHPExcel_Calculation { if ($pSheet !== NULL) { // echo 'Current sheet name is '.$pSheet->getTitle().'
'; // echo 'Range reference is '.$pRange.'
'; - if (strpos ($pRange, '!') !== false) { + if (strpos ($pRange, '!') !== FALSE) { // echo '$pRange reference includes sheet reference
'; - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true); + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, TRUE); $pSheet = $this->_workbook->getSheetByName($worksheetReference[0]); // echo 'New sheet name is '.$pSheet->getTitle().'
'; $pRange = $worksheetReference[1]; @@ -3709,7 +3713,7 @@ class PHPExcel_Calculation { 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 @@ -3720,7 +3724,7 @@ class PHPExcel_Calculation { if ($pSheet->cellExists($reference)) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); } else { - $returnValue[$currentRow][$currentCol] = null; + $returnValue[$currentRow][$currentCol] = NULL; } } } @@ -3744,7 +3748,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/Cell.php b/Classes/PHPExcel/Cell.php index ea37c7ec..ab8b472c 100644 --- a/Classes/PHPExcel/Cell.php +++ b/Classes/PHPExcel/Cell.php @@ -288,7 +288,10 @@ class PHPExcel_Cell if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) { try { // echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value
'; - $result = $this->getParent()->getParent()->getCalculationEngine()->calculateCellValue($this,$resetLog); + $result = PHPExcel_Calculation::getInstance( + $this->getParent()->getParent() + )->calculateCellValue($this,$resetLog); +// $result = $this->getParent()->getParent()->getCalculationEngine()->calculateCellValue($this,$resetLog); // echo $this->getCoordinate().' calculation result is '.$result.'
'; } catch ( PHPExcel_Exception $ex ) { if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) { 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, From b589fab56bbe12e9378a901dbf6a06cdbff14020 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Tue, 12 Feb 2013 12:44:31 +0000 Subject: [PATCH 05/45] Selective calculation cache clearance and adjustment for unsetting or renaming worksheets --- Classes/PHPExcel.php | 41 +++++++++++++++++++--------- Classes/PHPExcel/Calculation.php | 19 +++++++++++++ Classes/PHPExcel/Worksheet.php | 46 +++++++++++++++++++++++--------- 3 files changed, 82 insertions(+), 24 deletions(-) diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php index 901cb16d..ff6a10d7 100644 --- a/Classes/PHPExcel.php +++ b/Classes/PHPExcel.php @@ -143,8 +143,7 @@ class PHPExcel $this->addCellStyleXf(new PHPExcel_Style); } - - /** + /** * Destroy this workbook */ public function __destruct() { @@ -157,7 +156,9 @@ class PHPExcel * 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(); $this->_workSheetCollection[$k] = null; @@ -171,8 +172,8 @@ class PHPExcel * * @return PHPExcel_Calculation */ - public function getCalculationEngine() { - + public function getCalculationEngine() + { return $this->_calculationEngine; } // function getCellCacheController() @@ -262,7 +263,9 @@ class PHPExcel public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = NULL) { if ($this->sheetNameExists($pSheet->getTitle())) { - throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first."); + throw new PHPExcel_Exception( + "Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first." + ); } if($iSheetIndex === NULL) { @@ -295,8 +298,13 @@ class PHPExcel */ public function removeSheetByIndex($pIndex = 0) { - if ($pIndex > count($this->_workSheetCollection) - 1) { - throw new PHPExcel_Exception("Sheet index is out of bounds."); + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to remove a sheet by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); } else { array_splice($this->_workSheetCollection, $pIndex, 1); } @@ -317,8 +325,13 @@ class PHPExcel */ public function getSheet($pIndex = 0) { - if ($pIndex > count($this->_workSheetCollection) - 1) { - throw new PHPExcel_Exception("Sheet index is out of bounds."); + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}." + ); } else { return $this->_workSheetCollection[$pIndex]; } @@ -424,8 +437,12 @@ class PHPExcel */ public function setActiveSheetIndex($pIndex = 0) { - if ($pIndex > count($this->_workSheetCollection) - 1) { - throw new PHPExcel_Exception("Active sheet index is out of bounds."); + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to set a sheet active by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); } else { $this->_activeSheetIndex = $pIndex; } diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index e04fd695..a1e51bc4 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -1864,6 +1864,25 @@ class PHPExcel_Calculation { $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 clearCalculationCache() + + /** + * 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 clearCalculationCache() + /** * Get the currently defined locale code diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index ec201ab5..5a0ea544 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -378,13 +378,25 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function disconnectCells() { $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; } /** + * Code to execute when this worksheet is unset() + * + */ + function __destruct() { + if ($this->_cellCollection !== NULL) { + $this->disconnectCells(); + } + PHPExcel_Calculation::getInstance($this->_parent) + ->clearCalculationCacheForWorksheet($this->_title); + } + + /** * Return the cache controller for the cell collection * * @return PHPExcel_CachedObjectStorage_xxx @@ -703,14 +715,20 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $cellValue = $cell->getCalculatedValue(); // To formatted string - $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()); + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString( + $cellValue, + $this->_parent->getCellXfByIndex($cell->getXfIndex()) + ->getNumberFormat()->getFormatCode() + ); $autoSizes[$cell->getColumn()] = max( (float)$autoSizes[$cell->getColumn()], (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $this->_parent->getCellXfByIndex($cell->getXfIndex()) + ->getFont(), $cellValue, - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->_parent->getCellXfByIndex($cell->getXfIndex()) + ->getAlignment()->getTextRotation(), $this->getDefaultStyle()->getFont() ) ); @@ -791,16 +809,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) { @@ -822,11 +840,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; @@ -1092,7 +1112,7 @@ 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? @@ -1184,7 +1204,7 @@ 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? @@ -2416,7 +2436,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ($formatData) { $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); - $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString($returnValue[$rRef][$cRef], $style->getNumberFormat()->getFormatCode()); + $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( + $returnValue[$rRef][$cRef], $style->getNumberFormat()->getFormatCode() + ); } } else { // Cell holds a NULL From 245a1dc8323af98c0a44926db6c78f06083eb8e5 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 13 Feb 2013 09:01:36 +0000 Subject: [PATCH 06/45] __destroy methods for Excel and Worksheet objects --- Classes/PHPExcel.php | 9 +++++++++ Classes/PHPExcel/Worksheet.php | 12 +++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php index 5c66cf45..2a450c4c 100644 --- a/Classes/PHPExcel.php +++ b/Classes/PHPExcel.php @@ -133,6 +133,7 @@ class PHPExcel * */ public function disconnectWorksheets() { + $worksheet = NULL; foreach($this->_workSheetCollection as $k => &$worksheet) { $worksheet->disconnectCells(); $this->_workSheetCollection[$k] = null; @@ -141,6 +142,14 @@ class PHPExcel $this->_workSheetCollection = array(); } + /** + * Code to execute when this worksheet is unset() + * + */ + function __destruct() { + $this->disconnectWorksheets(); + } + /** * Get properties * diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index 2cdaca75..c8b70fe1 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -379,13 +379,23 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable public function disconnectCells() { $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; } /** + * Code to execute when this worksheet is unset() + * + */ + function __destruct() { + if ($this->_cellCollection !== NULL) { + $this->disconnectCells(); + } + } + + /** * Return the cache controller for the cell collection * * @return PHPExcel_CachedObjectStorage_xxx From 6fd6b4d0443aca9d8f29d4de2f168b12e1512e21 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 13 Feb 2013 13:17:16 +0000 Subject: [PATCH 07/45] Fix PHPExcel object destructor --- Classes/PHPExcel.php | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php index 4116b6c4..99435ca7 100644 --- a/Classes/PHPExcel.php +++ b/Classes/PHPExcel.php @@ -143,8 +143,9 @@ class PHPExcel $this->addCellStyleXf(new PHPExcel_Style); } - /** - * Destroy this workbook + /** + * Code to execute when this worksheet is unset() + * */ public function __destruct() { PHPExcel_Calculation::unsetInstance($this); @@ -177,14 +178,6 @@ class PHPExcel return $this->_calculationEngine; } // function getCellCacheController() - /** - * Code to execute when this worksheet is unset() - * - */ - function __destruct() { - $this->disconnectWorksheets(); - } - /** * Get properties * From 3886c47ebe1700009c89df9c25f2df94ea59236f Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 15 Feb 2013 15:42:06 +0000 Subject: [PATCH 08/45] Refactoring of calculation engine using the multiton pattern to eliminate caching issues when working with multiple workbooks Refactoring of calculation engine for improved performance and memory usage Refactoring of cell object to eliminate data duplication and reduce memory --- Classes/PHPExcel.php | 4 +- .../CachedObjectStorage/CacheBase.php | 22 + .../PHPExcel/CachedObjectStorage/Memory.php | 10 +- Classes/PHPExcel/CalcEngine/Logger.php | 109 + Classes/PHPExcel/Calculation.php | 238 +- Classes/PHPExcel/Calculation/Token/Stack.php | 4 +- Classes/PHPExcel/Cell.php | 63 +- Classes/PHPExcel/Worksheet.php | 4811 ++++++++--------- Classes/PHPExcel/Writer/CSV.php | 6 +- Classes/PHPExcel/Writer/Excel2007.php | 6 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 11 +- Classes/PHPExcel/Writer/Excel5.php | 8 +- Classes/PHPExcel/Writer/HTML.php | 6 +- 13 files changed, 2702 insertions(+), 2596 deletions(-) create mode 100644 Classes/PHPExcel/CalcEngine/Logger.php diff --git a/Classes/PHPExcel.php b/Classes/PHPExcel.php index 99435ca7..19213c24 100644 --- a/Classes/PHPExcel.php +++ b/Classes/PHPExcel.php @@ -70,7 +70,7 @@ class PHPExcel */ private $_workSheetCollection = array(); - /** + /** * Calculation Engine * * @var PHPExcel_Calculation @@ -878,7 +878,7 @@ class PHPExcel $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); } - // also do garbage collection for all the sheets + // also do garbage collection for all the sheets $sheet->garbageCollect(); } } diff --git a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php index 924b4b44..0651b4a3 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? * @@ -188,6 +193,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 * 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/CalcEngine/Logger.php b/Classes/PHPExcel/CalcEngine/Logger.php new file mode 100644 index 00000000..2cb893ef --- /dev/null +++ b/Classes/PHPExcel/CalcEngine/Logger.php @@ -0,0 +1,109 @@ +_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(array $cellReferencePath) { + // Only write the debug log if logging is enabled + if ($this->_writeDebugLog) { + $message = func_get_args(); + array_shift($message); + $cellReference = implode(' -> ', $cellReferencePath); + $message = implode($message); + if ($this->_echoDebugLog) { + echo $cellReference, (count($cellReferencePath) > 0 ? ' => ' : ''), $message,PHP_EOL; + } + $this->_debugLog[] = $cellReference . (count($cellReferencePath) > 0 ? ' => ' : '') . $message; + } + } // function _writeDebug() + + + public function clearLog() { + $this->_debugLog = array(); + } // function flushLogger() + + public function getLog() { + return $this->_debugLog; + } // function flushLogger() + + +} // class PHPExcel_Calculation_Logger + diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index a1e51bc4..e109865c 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -156,6 +156,15 @@ class PHPExcel_Calculation { '|' => 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 @@ -176,30 +185,6 @@ class PHPExcel_Calculation { */ 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; - - /** * An array of the nested cell references accessed by the calculation engine, used for the debug log * @@ -207,22 +192,14 @@ class PHPExcel_Calculation { * @var array of string * */ - private $debugLogStack = array(); + private $cyclicReferenceStack = array(); - /** - * The debug log generated by the calculation engine - * - * @access public - * @var array of string - * - */ - public $debugLog = array(); private $_cyclicFormulaCount = 0; private $_cyclicFormulaCell = ''; public $cyclicFormulaCount = 0; - private $_savedPrecision = 12; + private $_savedPrecision = 14; private static $_localeLanguage = 'en_us'; // US English (default locale) @@ -1688,7 +1665,7 @@ class PHPExcel_Calculation { private function __construct(PHPExcel $workbook = NULL) { - $setPrecision = (PHP_INT_SIZE == 4) ? 12 : 16; + $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16; $this->_savedPrecision = ini_get('precision'); if ($this->_savedPrecision < $setPrecision) { ini_set('precision',$setPrecision); @@ -1699,6 +1676,7 @@ class PHPExcel_Calculation { } $this->_workbook = $workbook; + $this->_debugLog = new PHPExcel_CalcEngine_Logger(); } // function __construct() @@ -1759,6 +1737,10 @@ class PHPExcel_Calculation { } // function flushInstance() + public function getDebugLog() { + return $this->_debugLog; + } + /** * __clone implementation. Cloning should not be allowed in a Singleton! * @@ -1871,7 +1853,7 @@ class PHPExcel_Calculation { if (isset($this->_calculationCache[$worksheetName])) { unset($this->_calculationCache[$worksheetName]); } - } // function clearCalculationCache() + } // function clearCalculationCacheForWorksheet() /** * Rename calculation cache for a specified worksheet @@ -1881,7 +1863,7 @@ class PHPExcel_Calculation { $this->_calculationCache[$toWorksheetName] = &$this->_calculationCache[$fromWorksheetName]; unset($this->_calculationCache[$fromWorksheetName]); } - } // function clearCalculationCache() + } // function renameCalculationCacheForWorksheet() /** @@ -2174,15 +2156,14 @@ class PHPExcel_Calculation { $returnArrayAsType = self::$returnArrayAsType; if ($resetLog) { // Initialise the logging settings if requested - $this->formulaError = NULL; - $this->debugLog = $this->debugLogStack = array(); + $this->formulaError = null; + $this->_debugLog->clearLog(); + $this->cyclicReferenceStack = array(); $this->_cyclicFormulaCount = 1; self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; } - if ($resetLog) { - } // Execute the calculation for the cell formula try { $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); @@ -2254,7 +2235,8 @@ class PHPExcel_Calculation { 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 = array(); // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache @@ -2277,9 +2259,11 @@ class PHPExcel_Calculation { public function getValueFromCache($worksheetName, $cellID, &$cellValue) { // Is calculation cacheing enabled? // Is the value present in calculation cache? - $this->_writeDebug('Testing cache value for cell ', $worksheetName, '!', $cellID); +//echo 'Test cache for ',$worksheetName,'!',$cellID,PHP_EOL; + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Testing cache value for cell ', $worksheetName, '!', $cellID); if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$worksheetName][$cellID]))) { - $this->_writeDebug('Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache'); +//echo 'Retrieve from cache',PHP_EOL; + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache'); // Return the cached result $cellValue = $this->_calculationCache[$worksheetName][$cellID]; return TRUE; @@ -2312,14 +2296,14 @@ class PHPExcel_Calculation { $formula = ltrim(substr($formula,1)); if (!isset($formula{0})) return self::_wrapResult($formula); - $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : NULL; + $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk"; if (($cellID !== NULL) && ($this->getValueFromCache($wsTitle, $cellID, $cellValue))) { return $cellValue; } - if (($wsTitle{0} !== "\x00") && (in_array($wsTitle.'!'.$cellID,$this->debugLogStack))) { + if (($wsTitle{0} !== "\x00") && (in_array($wsTitle.'!'.$cellID,$this->cyclicReferenceStack))) { if ($this->cyclicFormulaCount <= 0) { return $this->_raiseFormulaError('Cyclic Reference in Formula'); } elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) && @@ -2337,10 +2321,10 @@ class PHPExcel_Calculation { } } } - $this->debugLogStack[] = $wsTitle.'!'.$cellID; + $this->cyclicReferenceStack[] = $wsTitle.'!'.$cellID; // Parse the formula onto the token stack and calculate the value $cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell); - array_pop($this->debugLogStack); + array_pop($this->cyclicReferenceStack); // Save to calculation cache if ($cellID !== NULL) { @@ -2505,7 +2489,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); @@ -2540,7 +2524,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); @@ -2665,7 +2649,7 @@ class PHPExcel_Calculation { // 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; + $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; $regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION. '|'.self::CALCULATION_REGEXP_NUMBER. @@ -3019,9 +3003,10 @@ class PHPExcel_Calculation { private function _processTokenStack($tokens, $cellID = NULL, PHPExcel_Cell $pCell = NULL) { if ($tokens == FALSE) return FALSE; - // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet), - // so we store the parent worksheet so that we can re-attach it when necessary - $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : NULL; + // 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; // Loop through each token in turn @@ -3042,9 +3027,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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2)); } // Process the operation in the appropriate manner @@ -3064,7 +3049,7 @@ class PHPExcel_Calculation { 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) { list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); @@ -3145,13 +3130,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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($result)); $stack->push('Value',$result); break; case '|' : // Intersect @@ -3165,7 +3150,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($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($cellIntersect)); $stack->push('Value',$cellIntersect,$cellRef); break; } @@ -3177,11 +3162,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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluating Percentile of ', $this->_showValue($arg)); $multiplier = 0.01; } if (is_array($arg)) { @@ -3191,10 +3176,10 @@ class PHPExcel_Calculation { $matrixResult = $matrix1->arrayTimesEquals($multiplier); $result = $matrixResult->getArray(); } catch (PHPExcel_Exception $ex) { - $this->_writeDebug('JAMA Matrix Exception: ', $ex->getMessage()); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } - $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($result)); $stack->push('Value',$result); } else { $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack); @@ -3218,23 +3203,23 @@ class PHPExcel_Calculation { } $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { $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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } } } else { @@ -3251,7 +3236,7 @@ class PHPExcel_Calculation { 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($this->cyclicReferenceStack, 'Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { if ($this->_workbook->getSheetByName($matches[2])->cellExists($cellRef)) { $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); @@ -3262,18 +3247,18 @@ class PHPExcel_Calculation { } 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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluating Cell ', $cellRef, ' in current worksheet'); + if ($pCellParent->isDataSet($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE); $pCell->attach($pCellParent); } else { $cellValue = NULL; } - $this->_writeDebug('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } } } @@ -3286,7 +3271,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($this->cyclicReferenceStack, '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])) { @@ -3329,30 +3314,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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r)); // $result[] = $r; // } // } @@ -3372,7 +3357,7 @@ class PHPExcel_Calculation { } // } if ($functionName != 'MKMATRIX') { - $this->_writeDebug('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result)); } $stack->push('Value',self::_wrapResult($result)); } @@ -3383,7 +3368,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($this->cyclicReferenceStack, '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); @@ -3392,10 +3377,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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue)); $stack->push('Named Range',$cellValue,$namedRange); } else { return $this->_raiseFormulaError("undefined variable '$token'"); @@ -3425,12 +3410,12 @@ 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)); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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!')); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is a ', $this->_showTypeDetails('#VALUE!')); return FALSE; } } @@ -3447,14 +3432,14 @@ class PHPExcel_Calculation { $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($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Evaluating Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData)); $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack); $r = $stack->pop(); $result[$x] = $r['value']; @@ -3462,14 +3447,14 @@ 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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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($this->cyclicReferenceStack, 'Comparison Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Array',$result); return TRUE; @@ -3508,7 +3493,7 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Value',$result); return TRUE; @@ -3546,7 +3531,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($this->cyclicReferenceStack, 'JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } } else { @@ -3573,7 +3558,7 @@ 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!')); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails('#DIV/0!')); return FALSE; } else { $result = $operand1/$operand2; @@ -3588,29 +3573,17 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug('Evaluation Result is ', $this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Value',$result); 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 = array(); if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage); trigger_error($errorMessage, E_USER_ERROR); } // function _raiseFormulaError() @@ -3628,25 +3601,26 @@ class PHPExcel_Calculation { // 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.'
'; - if (strpos ($pRange, '!') !== FALSE) { -// echo '$pRange reference includes sheet reference
'; - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, TRUE); - $pSheet = $this->_workbook->getSheetByName($worksheetReference[0]); -// echo 'New sheet name is '.$pSheet->getTitle().'
'; - $pRange = $worksheetReference[1]; -// echo 'Adjusted 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',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 { @@ -3657,7 +3631,7 @@ class PHPExcel_Calculation { 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 { @@ -3686,15 +3660,15 @@ class PHPExcel_Calculation { // 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 = $this->_workbook->getSheetByName($worksheetReference[0]); -// echo 'New sheet name is '.$pSheet->getTitle().'
'; - $pRange = $worksheetReference[1]; -// echo 'Adjusted Range reference is '.$pRange.'
'; + if (strpos ($pRange, '!') !== false) { +// 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? @@ -3729,6 +3703,7 @@ 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 { @@ -3740,6 +3715,7 @@ 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 { 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 ab8b472c..e21674aa 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,7 @@ class PHPExcel_Cell * @return void **/ public function notifyCacheController() { - $this->_parent->getCellCacheController()->updateCacheData($this); + $this->_parent->updateCacheData($this); return $this; } @@ -118,7 +111,9 @@ class PHPExcel_Cell $this->_parent = NULL; } - public function attach($parent) { + public function attach(PHPExcel_CachedObjectStorage_CacheBase $parent) { + + $this->_parent = $parent; } @@ -126,23 +121,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 +156,7 @@ class PHPExcel_Cell */ public function getColumn() { - list($column) = sscanf($this->_coordinate, '%[A-Z]%d'); - return $column; + return $this->_parent->getCurrentColumn(); } /** @@ -177,8 +166,7 @@ class PHPExcel_Cell */ public function getRow() { - list(,$row) = sscanf($this->_coordinate, '%[A-Z]%d'); - return $row; + return $this->_parent->getCurrentRow(); } /** @@ -188,7 +176,7 @@ class PHPExcel_Cell */ public function getCoordinate() { - return $this->_coordinate; + return $this->_parent->getCurrentAddress(); } /** @@ -210,7 +198,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() ); } @@ -289,7 +277,7 @@ class PHPExcel_Cell try { // echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value
'; $result = PHPExcel_Calculation::getInstance( - $this->getParent()->getParent() + $this->getWorksheet()->getParent() )->calculateCellValue($this,$resetLog); // $result = $this->getParent()->getParent()->getCalculationEngine()->calculateCellValue($this,$resetLog); // echo $this->getCoordinate().' calculation result is '.$result.'
'; @@ -302,7 +290,7 @@ class PHPExcel_Cell $result = '#N/A'; throw( new PHPExcel_Calculation_Exception( - $this->getParent()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage() + $this->getWorksheet()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage() ) ); } @@ -391,7 +379,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()); } /** @@ -406,7 +394,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()); } /** @@ -422,7 +410,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(); } @@ -439,7 +427,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()); } /** @@ -454,7 +442,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()); } /** @@ -470,7 +458,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(); } @@ -484,6 +472,15 @@ class PHPExcel_Cell return $this->_parent; } + /** + * Get parent worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_parent->getParent(); + } + /** * Re-bind parent * @@ -491,7 +488,7 @@ class PHPExcel_Cell * @return PHPExcel_Cell */ public function rebindParent(PHPExcel_Worksheet $parent) { - $this->_parent = $parent; + $this->_parent = $parent->getCellCacheController(); return $this->notifyCacheController(); } diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index 64ad1118..fad7c50c 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Worksheet + * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version ##VERSION##, ##DATE## + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## */ @@ -30,361 +30,361 @@ * PHPExcel_Worksheet * * @category PHPExcel - * @package PHPExcel_Worksheet + * @package PHPExcel_Worksheet * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet implements PHPExcel_IComparable { - /* Break types */ - const BREAK_NONE = 0; - const BREAK_ROW = 1; - const BREAK_COLUMN = 2; + /* Break types */ + const BREAK_NONE = 0; + const BREAK_ROW = 1; + const BREAK_COLUMN = 2; - /* Sheet state */ - const SHEETSTATE_VISIBLE = 'visible'; - const SHEETSTATE_HIDDEN = 'hidden'; - const SHEETSTATE_VERYHIDDEN = 'veryHidden'; + /* Sheet state */ + const SHEETSTATE_VISIBLE = 'visible'; + const SHEETSTATE_HIDDEN = 'hidden'; + const SHEETSTATE_VERYHIDDEN = 'veryHidden'; - /** - * Invalid characters in sheet title - * - * @var array - */ - private static $_invalidCharacters = array('*', ':', '/', '\\', '?', '[', ']'); + /** + * Invalid characters in sheet title + * + * @var array + */ + private static $_invalidCharacters = array('*', ':', '/', '\\', '?', '[', ']'); - /** - * Parent spreadsheet - * - * @var PHPExcel - */ - private $_parent; + /** + * Parent spreadsheet + * + * @var PHPExcel + */ + private $_parent; - /** - * Cacheable collection of cells - * - * @var PHPExcel_CachedObjectStorage_xxx - */ - private $_cellCollection = null; + /** + * Cacheable collection of cells + * + * @var PHPExcel_CachedObjectStorage_xxx + */ + private $_cellCollection = null; - /** - * Collection of row dimensions - * - * @var PHPExcel_Worksheet_RowDimension[] - */ - private $_rowDimensions = array(); + /** + * Collection of row dimensions + * + * @var PHPExcel_Worksheet_RowDimension[] + */ + private $_rowDimensions = array(); - /** - * Default row dimension - * - * @var PHPExcel_Worksheet_RowDimension - */ - private $_defaultRowDimension = null; + /** + * Default row dimension + * + * @var PHPExcel_Worksheet_RowDimension + */ + private $_defaultRowDimension = null; - /** - * Collection of column dimensions - * - * @var PHPExcel_Worksheet_ColumnDimension[] - */ - private $_columnDimensions = array(); + /** + * Collection of column dimensions + * + * @var PHPExcel_Worksheet_ColumnDimension[] + */ + private $_columnDimensions = array(); - /** - * Default column dimension - * - * @var PHPExcel_Worksheet_ColumnDimension - */ - private $_defaultColumnDimension = null; + /** + * Default column dimension + * + * @var PHPExcel_Worksheet_ColumnDimension + */ + private $_defaultColumnDimension = null; - /** - * Collection of drawings - * - * @var PHPExcel_Worksheet_BaseDrawing[] - */ - private $_drawingCollection = null; + /** + * Collection of drawings + * + * @var PHPExcel_Worksheet_BaseDrawing[] + */ + private $_drawingCollection = null; - /** - * Collection of Chart objects - * - * @var PHPExcel_Chart[] - */ - private $_chartCollection = array(); + /** + * Collection of Chart objects + * + * @var PHPExcel_Chart[] + */ + private $_chartCollection = array(); - /** - * Worksheet title - * - * @var string - */ - private $_title; + /** + * Worksheet title + * + * @var string + */ + private $_title; - /** - * Sheet state - * - * @var string - */ - private $_sheetState; + /** + * Sheet state + * + * @var string + */ + private $_sheetState; - /** - * Page setup - * - * @var PHPExcel_Worksheet_PageSetup - */ - private $_pageSetup; + /** + * Page setup + * + * @var PHPExcel_Worksheet_PageSetup + */ + private $_pageSetup; - /** - * Page margins - * - * @var PHPExcel_Worksheet_PageMargins - */ - private $_pageMargins; + /** + * Page margins + * + * @var PHPExcel_Worksheet_PageMargins + */ + private $_pageMargins; - /** - * Page header/footer - * - * @var PHPExcel_Worksheet_HeaderFooter - */ - private $_headerFooter; + /** + * Page header/footer + * + * @var PHPExcel_Worksheet_HeaderFooter + */ + private $_headerFooter; - /** - * Sheet view - * - * @var PHPExcel_Worksheet_SheetView - */ - private $_sheetView; + /** + * Sheet view + * + * @var PHPExcel_Worksheet_SheetView + */ + private $_sheetView; - /** - * Protection - * - * @var PHPExcel_Worksheet_Protection - */ - private $_protection; + /** + * Protection + * + * @var PHPExcel_Worksheet_Protection + */ + private $_protection; - /** - * Collection of styles - * - * @var PHPExcel_Style[] - */ - private $_styles = array(); + /** + * Collection of styles + * + * @var PHPExcel_Style[] + */ + private $_styles = array(); - /** - * Conditional styles. Indexed by cell coordinate, e.g. 'A1' - * - * @var array - */ - private $_conditionalStylesCollection = array(); + /** + * Conditional styles. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_conditionalStylesCollection = array(); - /** - * Is the current cell collection sorted already? - * - * @var boolean - */ - private $_cellCollectionIsSorted = false; + /** + * Is the current cell collection sorted already? + * + * @var boolean + */ + private $_cellCollectionIsSorted = false; - /** - * Collection of breaks - * - * @var array - */ - private $_breaks = array(); + /** + * Collection of breaks + * + * @var array + */ + private $_breaks = array(); - /** - * Collection of merged cell ranges - * - * @var array - */ - private $_mergeCells = array(); + /** + * Collection of merged cell ranges + * + * @var array + */ + private $_mergeCells = array(); - /** - * Collection of protected cell ranges - * - * @var array - */ - private $_protectedCells = array(); + /** + * Collection of protected cell ranges + * + * @var array + */ + private $_protectedCells = array(); - /** - * Autofilter Range and selection - * - * @var PHPExcel_Worksheet_AutoFilter - */ - private $_autoFilter = NULL; + /** + * Autofilter Range and selection + * + * @var PHPExcel_Worksheet_AutoFilter + */ + private $_autoFilter = NULL; - /** - * Freeze pane - * - * @var string - */ - private $_freezePane = ''; + /** + * Freeze pane + * + * @var string + */ + private $_freezePane = ''; - /** - * Show gridlines? - * - * @var boolean - */ - private $_showGridlines = true; + /** + * Show gridlines? + * + * @var boolean + */ + private $_showGridlines = true; - /** - * Print gridlines? - * - * @var boolean - */ - private $_printGridlines = false; + /** + * Print gridlines? + * + * @var boolean + */ + private $_printGridlines = false; - /** - * Show row and column headers? - * - * @var boolean - */ - private $_showRowColHeaders = true; + /** + * Show row and column headers? + * + * @var boolean + */ + private $_showRowColHeaders = true; - /** - * Show summary below? (Row/Column outline) - * - * @var boolean - */ - private $_showSummaryBelow = true; + /** + * Show summary below? (Row/Column outline) + * + * @var boolean + */ + private $_showSummaryBelow = true; - /** - * Show summary right? (Row/Column outline) - * - * @var boolean - */ - private $_showSummaryRight = true; + /** + * Show summary right? (Row/Column outline) + * + * @var boolean + */ + private $_showSummaryRight = true; - /** - * Collection of comments - * - * @var PHPExcel_Comment[] - */ - private $_comments = array(); + /** + * Collection of comments + * + * @var PHPExcel_Comment[] + */ + private $_comments = array(); - /** - * Active cell. (Only one!) - * - * @var string - */ - private $_activeCell = 'A1'; + /** + * Active cell. (Only one!) + * + * @var string + */ + private $_activeCell = 'A1'; - /** - * Selected cells - * - * @var string - */ - private $_selectedCells = 'A1'; + /** + * Selected cells + * + * @var string + */ + private $_selectedCells = 'A1'; - /** - * Cached highest column - * - * @var string - */ - private $_cachedHighestColumn = 'A'; + /** + * Cached highest column + * + * @var string + */ + private $_cachedHighestColumn = 'A'; - /** - * Cached highest row - * - * @var int - */ - private $_cachedHighestRow = 1; + /** + * Cached highest row + * + * @var int + */ + private $_cachedHighestRow = 1; - /** - * Right-to-left? - * - * @var boolean - */ - private $_rightToLeft = false; + /** + * Right-to-left? + * + * @var boolean + */ + private $_rightToLeft = false; - /** - * Hyperlinks. Indexed by cell coordinate, e.g. 'A1' - * - * @var array - */ - private $_hyperlinkCollection = array(); + /** + * Hyperlinks. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_hyperlinkCollection = array(); - /** - * Data validation objects. Indexed by cell coordinate, e.g. 'A1' - * - * @var array - */ - private $_dataValidationCollection = array(); + /** + * Data validation objects. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_dataValidationCollection = array(); - /** - * Tab color - * - * @var PHPExcel_Style_Color - */ - private $_tabColor; + /** + * Tab color + * + * @var PHPExcel_Style_Color + */ + private $_tabColor; - /** - * Dirty flag - * - * @var boolean - */ - private $_dirty = true; + /** + * Dirty flag + * + * @var boolean + */ + private $_dirty = true; - /** - * Hash - * - * @var string - */ - private $_hash = null; + /** + * Hash + * + * @var string + */ + private $_hash = null; - /** - * Create a new worksheet - * - * @param PHPExcel $pParent - * @param string $pTitle - */ - public function __construct(PHPExcel $pParent = null, $pTitle = 'Worksheet') - { - // Set parent and title - $this->_parent = $pParent; - $this->setTitle($pTitle, FALSE); - $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); + /** + * Create a new worksheet + * + * @param PHPExcel $pParent + * @param string $pTitle + */ + public function __construct(PHPExcel $pParent = null, $pTitle = 'Worksheet') + { + // Set parent and title + $this->_parent = $pParent; + $this->setTitle($pTitle, FALSE); + $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); - $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); + $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); - // Set page setup - $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); + // Set page setup + $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); - // Set page margins - $this->_pageMargins = new PHPExcel_Worksheet_PageMargins(); + // Set page margins + $this->_pageMargins = new PHPExcel_Worksheet_PageMargins(); - // Set page header/footer - $this->_headerFooter = new PHPExcel_Worksheet_HeaderFooter(); + // Set page header/footer + $this->_headerFooter = new PHPExcel_Worksheet_HeaderFooter(); - // Set sheet view - $this->_sheetView = new PHPExcel_Worksheet_SheetView(); + // Set sheet view + $this->_sheetView = new PHPExcel_Worksheet_SheetView(); - // Drawing collection - $this->_drawingCollection = new ArrayObject(); + // Drawing collection + $this->_drawingCollection = new ArrayObject(); - // Chart collection - $this->_chartCollection = new ArrayObject(); + // Chart collection + $this->_chartCollection = new ArrayObject(); - // Protection - $this->_protection = new PHPExcel_Worksheet_Protection(); + // Protection + $this->_protection = new PHPExcel_Worksheet_Protection(); - // Default row dimension - $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(NULL); + // Default row dimension + $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(NULL); - // Default column dimension - $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(NULL); + // Default column dimension + $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(NULL); - $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(NULL, $this); - } + $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(NULL, $this); + } - /** - * Disconnect all cells from this PHPExcel_Worksheet object, - * typically so that the worksheet object can be unset - * - */ + /** + * Disconnect all cells from this PHPExcel_Worksheet object, + * typically so that the worksheet object can be unset + * + */ public function disconnectCells() { - $this->_cellCollection->unsetWorksheetCells(); + $this->_cellCollection->unsetWorksheetCells(); $this->_cellCollection = NULL; - // detach ourself from the workbook, so that it can then delete this worksheet successfully - $this->_parent = null; - } + // detach ourself from the workbook, so that it can then delete this worksheet successfully + $this->_parent = null; + } - /** + /** * Code to execute when this worksheet is unset() * */ @@ -397,1502 +397,1497 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } /** - * Return the cache controller for the cell collection - * - * @return PHPExcel_CachedObjectStorage_xxx - */ + * Return the cache controller for the cell collection + * + * @return PHPExcel_CachedObjectStorage_xxx + */ public function getCellCacheController() { - return $this->_cellCollection; - } // function getCellCacheController() + return $this->_cellCollection; + } // function getCellCacheController() - /** - * Get array of invalid characters for sheet title - * - * @return array - */ - public static function getInvalidCharacters() - { - return self::$_invalidCharacters; - } + /** + * Get array of invalid characters for sheet title + * + * @return array + */ + public static function getInvalidCharacters() + { + return self::$_invalidCharacters; + } - /** - * Check sheet title for valid Excel syntax - * - * @param string $pValue The string to check - * @return string The valid string - * @throws PHPExcel_Exception - */ - private static function _checkSheetTitle($pValue) - { - // Some of the printable ASCII characters are invalid: * : / \ ? [ ] - if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) { - throw new PHPExcel_Exception('Invalid character found in sheet title'); - } + /** + * Check sheet title for valid Excel syntax + * + * @param string $pValue The string to check + * @return string The valid string + * @throws PHPExcel_Exception + */ + private static function _checkSheetTitle($pValue) + { + // Some of the printable ASCII characters are invalid: * : / \ ? [ ] + if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) { + throw new PHPExcel_Exception('Invalid character found in sheet title'); + } - // Maximum 31 characters allowed for sheet title - if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { - throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet title.'); - } + // Maximum 31 characters allowed for sheet title + if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { + throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet title.'); + } - return $pValue; - } + return $pValue; + } - /** - * Get collection of cells - * - * @param boolean $pSorted Also sort the cell collection? - * @return PHPExcel_Cell[] - */ - public function getCellCollection($pSorted = true) - { - if ($pSorted) { - // Re-order cell collection - return $this->sortCellCollection(); - } - if ($this->_cellCollection !== NULL) { - return $this->_cellCollection->getCellList(); - } - return array(); - } + /** + * Get collection of cells + * + * @param boolean $pSorted Also sort the cell collection? + * @return PHPExcel_Cell[] + */ + public function getCellCollection($pSorted = true) + { + if ($pSorted) { + // Re-order cell collection + return $this->sortCellCollection(); + } + if ($this->_cellCollection !== NULL) { + return $this->_cellCollection->getCellList(); + } + return array(); + } - /** - * Sort collection of cells - * - * @return PHPExcel_Worksheet - */ - public function sortCellCollection() - { - if ($this->_cellCollection !== NULL) { - return $this->_cellCollection->getSortedCellList(); - } - return array(); - } + /** + * Sort collection of cells + * + * @return PHPExcel_Worksheet + */ + public function sortCellCollection() + { + if ($this->_cellCollection !== NULL) { + return $this->_cellCollection->getSortedCellList(); + } + return array(); + } - /** - * Get collection of row dimensions - * - * @return PHPExcel_Worksheet_RowDimension[] - */ - public function getRowDimensions() - { - return $this->_rowDimensions; - } + /** + * Get collection of row dimensions + * + * @return PHPExcel_Worksheet_RowDimension[] + */ + public function getRowDimensions() + { + return $this->_rowDimensions; + } - /** - * Get default row dimension - * - * @return PHPExcel_Worksheet_RowDimension - */ - public function getDefaultRowDimension() - { - return $this->_defaultRowDimension; - } + /** + * Get default row dimension + * + * @return PHPExcel_Worksheet_RowDimension + */ + public function getDefaultRowDimension() + { + return $this->_defaultRowDimension; + } - /** - * Get collection of column dimensions - * - * @return PHPExcel_Worksheet_ColumnDimension[] - */ - public function getColumnDimensions() - { - return $this->_columnDimensions; - } + /** + * Get collection of column dimensions + * + * @return PHPExcel_Worksheet_ColumnDimension[] + */ + public function getColumnDimensions() + { + return $this->_columnDimensions; + } - /** - * Get default column dimension - * - * @return PHPExcel_Worksheet_ColumnDimension - */ - public function getDefaultColumnDimension() - { - return $this->_defaultColumnDimension; - } + /** + * Get default column dimension + * + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getDefaultColumnDimension() + { + return $this->_defaultColumnDimension; + } - /** - * Get collection of drawings - * - * @return PHPExcel_Worksheet_BaseDrawing[] - */ - public function getDrawingCollection() - { - return $this->_drawingCollection; - } + /** + * Get collection of drawings + * + * @return PHPExcel_Worksheet_BaseDrawing[] + */ + public function getDrawingCollection() + { + return $this->_drawingCollection; + } - /** - * Get collection of charts - * - * @return PHPExcel_Chart[] - */ - public function getChartCollection() - { - return $this->_chartCollection; - } + /** + * Get collection of charts + * + * @return PHPExcel_Chart[] + */ + public function getChartCollection() + { + return $this->_chartCollection; + } - /** - * Add chart - * - * @param PHPExcel_Chart $pChart - * @param int|null $iChartIndex Index where chart should go (0,1,..., or null for last) - * @return PHPExcel_Chart - */ - public function addChart(PHPExcel_Chart $pChart = null, $iChartIndex = null) - { - $pChart->setWorksheet($this); - if (is_null($iChartIndex)) { - $this->_chartCollection[] = $pChart; - } else { - // Insert the chart at the requested index - array_splice($this->_chartCollection, $iChartIndex, 0, array($pChart)); - } + /** + * Add chart + * + * @param PHPExcel_Chart $pChart + * @param int|null $iChartIndex Index where chart should go (0,1,..., or null for last) + * @return PHPExcel_Chart + */ + public function addChart(PHPExcel_Chart $pChart = null, $iChartIndex = null) + { + $pChart->setWorksheet($this); + if (is_null($iChartIndex)) { + $this->_chartCollection[] = $pChart; + } else { + // Insert the chart at the requested index + array_splice($this->_chartCollection, $iChartIndex, 0, array($pChart)); + } - return $pChart; - } + return $pChart; + } - /** - * Return the count of charts on this worksheet - * - * @return int The number of charts - */ - public function getChartCount() - { - return count($this->_chartCollection); - } + /** + * Return the count of charts on this worksheet + * + * @return int The number of charts + */ + public function getChartCount() + { + return count($this->_chartCollection); + } - /** - * Get a chart by its index position - * - * @param string $index Chart index position - * @return false|PHPExcel_Chart - * @throws PHPExcel_Exception - */ - public function getChartByIndex($index = null) - { - $chartCount = count($this->_chartCollection); - if ($chartCount == 0) { - return false; - } - if (is_null($index)) { - $index = --$chartCount; - } - if (!isset($this->_chartCollection[$index])) { - return false; - } + /** + * Get a chart by its index position + * + * @param string $index Chart index position + * @return false|PHPExcel_Chart + * @throws PHPExcel_Exception + */ + public function getChartByIndex($index = null) + { + $chartCount = count($this->_chartCollection); + if ($chartCount == 0) { + return false; + } + if (is_null($index)) { + $index = --$chartCount; + } + if (!isset($this->_chartCollection[$index])) { + return false; + } - return $this->_chartCollection[$index]; - } + return $this->_chartCollection[$index]; + } - /** - * Return an array of the names of charts on this worksheet - * - * @return string[] The names of charts - * @throws PHPExcel_Exception - */ - public function getChartNames() - { - $chartNames = array(); - foreach($this->_chartCollection as $chart) { - $chartNames[] = $chart->getName(); - } - return $chartNames; - } + /** + * Return an array of the names of charts on this worksheet + * + * @return string[] The names of charts + * @throws PHPExcel_Exception + */ + public function getChartNames() + { + $chartNames = array(); + foreach($this->_chartCollection as $chart) { + $chartNames[] = $chart->getName(); + } + return $chartNames; + } - /** - * Get a chart by name - * - * @param string $chartName Chart name - * @return false|PHPExcel_Chart - * @throws PHPExcel_Exception - */ - public function getChartByName($chartName = '') - { - $chartCount = count($this->_chartCollection); - if ($chartCount == 0) { - return false; - } - foreach($this->_chartCollection as $index => $chart) { - if ($chart->getName() == $chartName) { - return $this->_chartCollection[$index]; - } - } - return false; - } + /** + * Get a chart by name + * + * @param string $chartName Chart name + * @return false|PHPExcel_Chart + * @throws PHPExcel_Exception + */ + public function getChartByName($chartName = '') + { + $chartCount = count($this->_chartCollection); + if ($chartCount == 0) { + return false; + } + foreach($this->_chartCollection as $index => $chart) { + if ($chart->getName() == $chartName) { + return $this->_chartCollection[$index]; + } + } + return false; + } - /** - * Refresh column dimensions - * - * @return PHPExcel_Worksheet - */ - public function refreshColumnDimensions() - { - $currentColumnDimensions = $this->getColumnDimensions(); - $newColumnDimensions = array(); + /** + * Refresh column dimensions + * + * @return PHPExcel_Worksheet + */ + public function refreshColumnDimensions() + { + $currentColumnDimensions = $this->getColumnDimensions(); + $newColumnDimensions = array(); - foreach ($currentColumnDimensions as $objColumnDimension) { - $newColumnDimensions[$objColumnDimension->getColumnIndex()] = $objColumnDimension; - } + foreach ($currentColumnDimensions as $objColumnDimension) { + $newColumnDimensions[$objColumnDimension->getColumnIndex()] = $objColumnDimension; + } - $this->_columnDimensions = $newColumnDimensions; + $this->_columnDimensions = $newColumnDimensions; - return $this; - } + return $this; + } - /** - * Refresh row dimensions - * - * @return PHPExcel_Worksheet - */ - public function refreshRowDimensions() - { - $currentRowDimensions = $this->getRowDimensions(); - $newRowDimensions = array(); + /** + * Refresh row dimensions + * + * @return PHPExcel_Worksheet + */ + public function refreshRowDimensions() + { + $currentRowDimensions = $this->getRowDimensions(); + $newRowDimensions = array(); - foreach ($currentRowDimensions as $objRowDimension) { - $newRowDimensions[$objRowDimension->getRowIndex()] = $objRowDimension; - } + foreach ($currentRowDimensions as $objRowDimension) { + $newRowDimensions[$objRowDimension->getRowIndex()] = $objRowDimension; + } - $this->_rowDimensions = $newRowDimensions; + $this->_rowDimensions = $newRowDimensions; - return $this; - } + return $this; + } - /** - * Calculate worksheet dimension - * - * @return string String containing the dimension of this worksheet - */ - public function calculateWorksheetDimension() - { - // Return - return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); - } + /** + * Calculate worksheet dimension + * + * @return string String containing the dimension of this worksheet + */ + public function calculateWorksheetDimension() + { + // Return + return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); + } - /** - * Calculate worksheet data dimension - * - * @return string String containing the dimension of this worksheet that actually contain data - */ - public function calculateWorksheetDataDimension() - { - // Return - return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow(); - } + /** + * Calculate worksheet data dimension + * + * @return string String containing the dimension of this worksheet that actually contain data + */ + public function calculateWorksheetDataDimension() + { + // Return + return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow(); + } - /** - * Calculate widths for auto-size columns - * - * @param boolean $calculateMergeCells Calculate merge cell width - * @return PHPExcel_Worksheet; - */ - public function calculateColumnWidths($calculateMergeCells = false) - { - // initialize $autoSizes array - $autoSizes = array(); - foreach ($this->getColumnDimensions() as $colDimension) { - if ($colDimension->getAutoSize()) { - $autoSizes[$colDimension->getColumnIndex()] = -1; - } - } + /** + * Calculate widths for auto-size columns + * + * @param boolean $calculateMergeCells Calculate merge cell width + * @return PHPExcel_Worksheet; + */ + public function calculateColumnWidths($calculateMergeCells = false) + { + // initialize $autoSizes array + $autoSizes = array(); + foreach ($this->getColumnDimensions() as $colDimension) { + if ($colDimension->getAutoSize()) { + $autoSizes[$colDimension->getColumnIndex()] = -1; + } + } - // There is only something to do if there are some auto-size columns - if (!empty($autoSizes)) { + // There is only something to do if there are some auto-size columns + if (!empty($autoSizes)) { - // build list of cells references that participate in a merge - $isMergeCell = array(); - foreach ($this->getMergeCells() as $cells) { - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) { - $isMergeCell[$cellReference] = true; - } - } + // build list of cells references that participate in a merge + $isMergeCell = array(); + foreach ($this->getMergeCells() as $cells) { + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) { + $isMergeCell[$cellReference] = true; + } + } - // loop through all cells in the worksheet - foreach ($this->getCellCollection(false) as $cellID) { - $cell = $this->getCell($cellID); - if (isset($autoSizes[$cell->getColumn()])) { - // Determine width if cell does not participate in a merge - if (!isset($isMergeCell[$cell->getCoordinate()])) { - // Calculated value - $cellValue = $cell->getCalculatedValue(); - - // To formatted string + // loop through all cells in the worksheet + foreach ($this->getCellCollection(false) as $cellID) { + $cell = $this->getCell($cellID); + if (isset($autoSizes[$this->_cellCollection->getCurrentColumn()])) { + // Determine width if cell does not participate in a merge + if (!isset($isMergeCell[$this->_cellCollection->getCurrentAddress()])) { + // Calculated value + // To formatted string $cellValue = PHPExcel_Style_NumberFormat::toFormattedString( - $cellValue, - $this->_parent->getCellXfByIndex($cell->getXfIndex()) - ->getNumberFormat()->getFormatCode() + $cell->getCalculatedValue(), + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode() ); - $autoSizes[$cell->getColumn()] = max( - (float)$autoSizes[$cell->getColumn()], - (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->_parent->getCellXfByIndex($cell->getXfIndex()) - ->getFont(), - $cellValue, - $this->_parent->getCellXfByIndex($cell->getXfIndex()) - ->getAlignment()->getTextRotation(), - $this->getDefaultStyle()->getFont() - ) - ); - } - } - } + $autoSizes[$this->_cellCollection->getCurrentColumn()] = max( + (float) $autoSizes[$this->_cellCollection->getCurrentColumn()], + (float)PHPExcel_Shared_Font::calculateColumnWidth( + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $cellValue, + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getDefaultStyle()->getFont() + ) + ); + } + } + } - // adjust column widths - foreach ($autoSizes as $columnIndex => $width) { - if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); - $this->getColumnDimension($columnIndex)->setWidth($width); - } - } + // adjust column widths + foreach ($autoSizes as $columnIndex => $width) { + if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); + $this->getColumnDimension($columnIndex)->setWidth($width); + } + } - return $this; - } + return $this; + } - /** - * Get parent - * - * @return PHPExcel - */ + /** + * Get parent + * + * @return PHPExcel + */ public function getParent() { - return $this->_parent; - } + return $this->_parent; + } - /** - * Re-bind parent - * - * @param PHPExcel $parent - * @return PHPExcel_Worksheet - */ + /** + * Re-bind parent + * + * @param PHPExcel $parent + * @return PHPExcel_Worksheet + */ public function rebindParent(PHPExcel $parent) { - $namedRanges = $this->_parent->getNamedRanges(); - foreach ($namedRanges as $namedRange) { - $parent->addNamedRange($namedRange); - } + $namedRanges = $this->_parent->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + $parent->addNamedRange($namedRange); + } - $this->_parent->removeSheetByIndex( - $this->_parent->getIndex($this) - ); - $this->_parent = $parent; + $this->_parent->removeSheetByIndex( + $this->_parent->getIndex($this) + ); + $this->_parent = $parent; - return $this; - } + return $this; + } - /** - * Get title - * - * @return string - */ - public function getTitle() - { - return $this->_title; - } + /** + * Get title + * + * @return string + */ + public function getTitle() + { + return $this->_title; + } - /** - * Set title - * - * @param string $pValue String containing the dimension of this worksheet - * @param string $updateFormulaCellReferences boolean Flag indicating whether cell references in formulae should - * be updated to reflect the new sheet name. - * 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) - { - // Is this a 'rename' or not? - if ($this->getTitle() == $pValue) { - return $this; - } + /** + * Set title + * + * @param string $pValue String containing the dimension of this worksheet + * @param string $updateFormulaCellReferences boolean Flag indicating whether cell references in formulae should + * be updated to reflect the new sheet name. + * 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) + { + // Is this a 'rename' or not? + if ($this->getTitle() == $pValue) { + return $this; + } - // Syntax check - self::_checkSheetTitle($pValue); + // Syntax check + self::_checkSheetTitle($pValue); - // Old title - $oldTitle = $this->getTitle(); + // Old title + $oldTitle = $this->getTitle(); if ($this->_parent) { - // Is there already such sheet name? + // Is there already such sheet name? if ($this->_parent->sheetNameExists($pValue)) { - // Use name, but append with lowest possible integer + // 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; + if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); + } + $i = 1; while ($this->_parent->sheetNameExists($pValue . ' ' . $i)) { - ++$i; - if ($i == 10) { - if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { - $pValue = PHPExcel_Shared_String::Substring($pValue,0,28); - } - } elseif ($i == 100) { - if (PHPExcel_Shared_String::CountCharacters($pValue) > 27) { - $pValue = PHPExcel_Shared_String::Substring($pValue,0,27); - } - } - } + ++$i; + if ($i == 10) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,28); + } + } elseif ($i == 100) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 27) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,27); + } + } + } - $altTitle = $pValue . ' ' . $i; - return $this->setTitle($altTitle,$updateFormulaCellReferences); - } - } + $altTitle = $pValue . ' ' . $i; + return $this->setTitle($altTitle,$updateFormulaCellReferences); + } + } - // Set title - $this->_title = $pValue; - $this->_dirty = true; + // Set title + $this->_title = $pValue; + $this->_dirty = true; if ($this->_parent) { - // New title - $newTitle = $this->getTitle(); + // New title + $newTitle = $this->getTitle(); PHPExcel_Calculation::getInstance($this->_parent) ->renameCalculationCacheForWorksheet($oldTitle, $newTitle); - if ($updateFormulaCellReferences) + if ($updateFormulaCellReferences) PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_parent, $oldTitle, $newTitle); - } + } - return $this; - } + return $this; + } - /** - * Get sheet state - * - * @return string Sheet state (visible, hidden, veryHidden) - */ + /** + * Get sheet state + * + * @return string Sheet state (visible, hidden, veryHidden) + */ public function getSheetState() { - return $this->_sheetState; - } + return $this->_sheetState; + } - /** - * Set sheet state - * - * @param string $value Sheet state (visible, hidden, veryHidden) - * @return PHPExcel_Worksheet - */ + /** + * Set sheet state + * + * @param string $value Sheet state (visible, hidden, veryHidden) + * @return PHPExcel_Worksheet + */ public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { - $this->_sheetState = $value; - return $this; - } + $this->_sheetState = $value; + return $this; + } - /** - * Get page setup - * - * @return PHPExcel_Worksheet_PageSetup - */ - public function getPageSetup() - { - return $this->_pageSetup; - } + /** + * Get page setup + * + * @return PHPExcel_Worksheet_PageSetup + */ + public function getPageSetup() + { + return $this->_pageSetup; + } - /** - * Set page setup - * - * @param PHPExcel_Worksheet_PageSetup $pValue - * @return PHPExcel_Worksheet - */ - public function setPageSetup(PHPExcel_Worksheet_PageSetup $pValue) - { - $this->_pageSetup = $pValue; - return $this; - } + /** + * Set page setup + * + * @param PHPExcel_Worksheet_PageSetup $pValue + * @return PHPExcel_Worksheet + */ + public function setPageSetup(PHPExcel_Worksheet_PageSetup $pValue) + { + $this->_pageSetup = $pValue; + return $this; + } - /** - * Get page margins - * - * @return PHPExcel_Worksheet_PageMargins - */ - public function getPageMargins() - { - return $this->_pageMargins; - } + /** + * Get page margins + * + * @return PHPExcel_Worksheet_PageMargins + */ + public function getPageMargins() + { + return $this->_pageMargins; + } - /** - * Set page margins - * - * @param PHPExcel_Worksheet_PageMargins $pValue - * @return PHPExcel_Worksheet - */ - public function setPageMargins(PHPExcel_Worksheet_PageMargins $pValue) - { - $this->_pageMargins = $pValue; - return $this; - } + /** + * Set page margins + * + * @param PHPExcel_Worksheet_PageMargins $pValue + * @return PHPExcel_Worksheet + */ + public function setPageMargins(PHPExcel_Worksheet_PageMargins $pValue) + { + $this->_pageMargins = $pValue; + return $this; + } - /** - * Get page header/footer - * - * @return PHPExcel_Worksheet_HeaderFooter - */ - public function getHeaderFooter() - { - return $this->_headerFooter; - } + /** + * Get page header/footer + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function getHeaderFooter() + { + return $this->_headerFooter; + } - /** - * Set page header/footer - * - * @param PHPExcel_Worksheet_HeaderFooter $pValue - * @return PHPExcel_Worksheet - */ - public function setHeaderFooter(PHPExcel_Worksheet_HeaderFooter $pValue) - { - $this->_headerFooter = $pValue; - return $this; - } + /** + * Set page header/footer + * + * @param PHPExcel_Worksheet_HeaderFooter $pValue + * @return PHPExcel_Worksheet + */ + public function setHeaderFooter(PHPExcel_Worksheet_HeaderFooter $pValue) + { + $this->_headerFooter = $pValue; + return $this; + } - /** - * Get sheet view - * - * @return PHPExcel_Worksheet_SheetView - */ - public function getSheetView() - { - return $this->_sheetView; - } + /** + * Get sheet view + * + * @return PHPExcel_Worksheet_SheetView + */ + public function getSheetView() + { + return $this->_sheetView; + } - /** - * Set sheet view - * - * @param PHPExcel_Worksheet_SheetView $pValue - * @return PHPExcel_Worksheet - */ - public function setSheetView(PHPExcel_Worksheet_SheetView $pValue) - { - $this->_sheetView = $pValue; - return $this; - } + /** + * Set sheet view + * + * @param PHPExcel_Worksheet_SheetView $pValue + * @return PHPExcel_Worksheet + */ + public function setSheetView(PHPExcel_Worksheet_SheetView $pValue) + { + $this->_sheetView = $pValue; + return $this; + } - /** - * Get Protection - * - * @return PHPExcel_Worksheet_Protection - */ - public function getProtection() - { - return $this->_protection; - } + /** + * Get Protection + * + * @return PHPExcel_Worksheet_Protection + */ + public function getProtection() + { + return $this->_protection; + } - /** - * Set Protection - * - * @param PHPExcel_Worksheet_Protection $pValue - * @return PHPExcel_Worksheet - */ - public function setProtection(PHPExcel_Worksheet_Protection $pValue) - { - $this->_protection = $pValue; - $this->_dirty = true; + /** + * Set Protection + * + * @param PHPExcel_Worksheet_Protection $pValue + * @return PHPExcel_Worksheet + */ + public function setProtection(PHPExcel_Worksheet_Protection $pValue) + { + $this->_protection = $pValue; + $this->_dirty = true; - return $this; - } + return $this; + } - /** - * Get highest worksheet column - * - * @return string Highest column name - */ - public function getHighestColumn() - { - return $this->_cachedHighestColumn; - } + /** + * Get highest worksheet column + * + * @return string Highest column name + */ + public function getHighestColumn() + { + return $this->_cachedHighestColumn; + } - /** - * Get highest worksheet column that contains data - * - * @return string Highest column name that contains data - */ - public function getHighestDataColumn() - { - return $this->_cellCollection->getHighestColumn(); - } + /** + * Get highest worksheet column that contains data + * + * @return string Highest column name that contains data + */ + public function getHighestDataColumn() + { + return $this->_cellCollection->getHighestColumn(); + } - /** - * Get highest worksheet row - * - * @return int Highest row number - */ - public function getHighestRow() - { - return $this->_cachedHighestRow; - } + /** + * Get highest worksheet row + * + * @return int Highest row number + */ + public function getHighestRow() + { + return $this->_cachedHighestRow; + } - /** - * Get highest worksheet row that contains data - * - * @return string Highest row number that contains data - */ - public function getHighestDataRow() - { - return $this->_cellCollection->getHighestRow(); - } + /** + * Get highest worksheet row that contains data + * + * @return string Highest row number that contains data + */ + public function getHighestDataRow() + { + return $this->_cellCollection->getHighestRow(); + } - /** - * Get highest worksheet column and highest row that have cell records - * - * @return array Highest column name and highest row number - */ - public function getHighestRowAndColumn() - { - return $this->_cellCollection->getHighestRowAndColumn(); - } + /** + * Get highest worksheet column and highest row that have cell records + * + * @return array Highest column name and highest row number + */ + public function getHighestRowAndColumn() + { + return $this->_cellCollection->getHighestRowAndColumn(); + } - /** - * Set a cell value - * - * @param string $pCoordinate Coordinate of the cell - * @param mixed $pValue Value of the cell - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValue($pCoordinate = 'A1', $pValue = null, $returnCell = false) - { - $cell = $this->getCell($pCoordinate)->setValue($pValue); - return ($returnCell) ? $cell : $this; - } + /** + * Set a cell value + * + * @param string $pCoordinate Coordinate of the cell + * @param mixed $pValue Value of the cell + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValue($pCoordinate = 'A1', $pValue = null, $returnCell = false) + { + $cell = $this->getCell($pCoordinate)->setValue($pValue); + return ($returnCell) ? $cell : $this; + } - /** - * Set a cell value by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell (A = 0) - * @param string $pRow Numeric row coordinate of the cell - * @param mixed $pValue Value of the cell - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $returnCell = false) - { - $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValue($pValue); - return ($returnCell) ? $cell : $this; - } + /** + * Set a cell value by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell (A = 0) + * @param string $pRow Numeric row coordinate of the cell + * @param mixed $pValue Value of the cell + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $returnCell = false) + { + $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValue($pValue); + return ($returnCell) ? $cell : $this; + } - /** - * Set a cell value - * - * @param string $pCoordinate Coordinate of the cell - * @param mixed $pValue Value of the cell - * @param string $pDataType Explicit data type - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValueExplicit($pCoordinate = 'A1', $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) - { - // Set value - $cell = $this->getCell($pCoordinate)->setValueExplicit($pValue, $pDataType); - return ($returnCell) ? $cell : $this; - } + /** + * Set a cell value + * + * @param string $pCoordinate Coordinate of the cell + * @param mixed $pValue Value of the cell + * @param string $pDataType Explicit data type + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueExplicit($pCoordinate = 'A1', $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) + { + // Set value + $cell = $this->getCell($pCoordinate)->setValueExplicit($pValue, $pDataType); + return ($returnCell) ? $cell : $this; + } - /** - * Set a cell value by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @param mixed $pValue Value of the cell - * @param string $pDataType Explicit data type - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) - { - $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType); - return ($returnCell) ? $cell : $this; - } + /** + * Set a cell value by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @param mixed $pValue Value of the cell + * @param string $pDataType Explicit data type + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) + { + $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType); + return ($returnCell) ? $cell : $this; + } - /** - * Get cell at a specific coordinate - * - * @param string $pCoordinate Coordinate of the cell - * @throws PHPExcel_Exception - * @return PHPExcel_Cell Cell that was found - */ - public function getCell($pCoordinate = 'A1') - { - // Check cell collection - if ($this->_cellCollection->isDataSet($pCoordinate)) { - return $this->_cellCollection->getCacheData($pCoordinate); - } + /** + * Get cell at a specific coordinate + * + * @param string $pCoordinate Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found + */ + public function getCell($pCoordinate = 'A1') + { + // Check cell collection + if ($this->_cellCollection->isDataSet($pCoordinate)) { + return $this->_cellCollection->getCacheData($pCoordinate); + } - // Worksheet reference? - if (strpos($pCoordinate, '!') !== false) { - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); + // Worksheet reference? + if (strpos($pCoordinate, '!') !== false) { + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); 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) { - $pCoordinate = $namedRange->getRange(); - return $namedRange->getWorksheet()->getCell($pCoordinate); - } - } + // 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) { + $pCoordinate = $namedRange->getRange(); + return $namedRange->getWorksheet()->getCell($pCoordinate); + } + } - // Uppercase coordinate - $pCoordinate = strtoupper($pCoordinate); + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); - } elseif (strpos($pCoordinate,'$') !== false) { - throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); - } else { - // Create new cell object + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); + } elseif (strpos($pCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } else { + // Create new cell object - // Coordinates - $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); + // Coordinates + $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); - $cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell($pCoordinate, NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this)); - $this->_cellCollectionIsSorted = false; + $cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this)); + $this->_cellCollectionIsSorted = false; - if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) - $this->_cachedHighestColumn = $aCoordinates[0]; + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) + $this->_cachedHighestColumn = $aCoordinates[0]; - $this->_cachedHighestRow = max($this->_cachedHighestRow,$aCoordinates[1]); + $this->_cachedHighestRow = max($this->_cachedHighestRow,$aCoordinates[1]); - // Cell needs appropriate xfIndex - $rowDimensions = $this->getRowDimensions(); - $columnDimensions = $this->getColumnDimensions(); + // Cell needs appropriate xfIndex + $rowDimensions = $this->getRowDimensions(); + $columnDimensions = $this->getColumnDimensions(); - if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { - // then there is a row dimension with explicit style, assign it to the cell - $cell->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); - } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { - // then there is a column dimension, assign it to the cell - $cell->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); - } else { - // set to default index - $cell->setXfIndex(0); - } + if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { + // then there is a row dimension with explicit style, assign it to the cell + $cell->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); + } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { + // then there is a column dimension, assign it to the cell + $cell->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); + } else { + // set to default index + $cell->setXfIndex(0); + } - return $cell; - } - } + return $cell; + } + } - /** - * Get cell at a specific coordinate by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @return PHPExcel_Cell Cell that was found - */ - public function getCellByColumnAndRow($pColumn = 0, $pRow = 1) - { - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); - $coordinate = $columnLetter . $pRow; + /** + * Get cell at a specific coordinate by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @return PHPExcel_Cell Cell that was found + */ + public function getCellByColumnAndRow($pColumn = 0, $pRow = 1) + { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); + $coordinate = $columnLetter . $pRow; - if (!$this->_cellCollection->isDataSet($coordinate)) { - $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell($coordinate, NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this)); - $this->_cellCollectionIsSorted = false; + if (!$this->_cellCollection->isDataSet($coordinate)) { + $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this)); + $this->_cellCollectionIsSorted = false; - if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) - $this->_cachedHighestColumn = $columnLetter; + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) + $this->_cachedHighestColumn = $columnLetter; - $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); + $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); - return $cell; - } + return $cell; + } - return $this->_cellCollection->getCacheData($coordinate); - } + return $this->_cellCollection->getCacheData($coordinate); + } - /** - * Cell at a specific coordinate exists? - * - * @param string $pCoordinate Coordinate of the cell - * @throws PHPExcel_Exception - * @return boolean - */ - public function cellExists($pCoordinate = 'A1') - { - // Worksheet reference? - if (strpos($pCoordinate, '!') !== false) { - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); + /** + * Cell at a specific coordinate exists? + * + * @param string $pCoordinate Coordinate of the cell + * @throws PHPExcel_Exception + * @return boolean + */ + public function cellExists($pCoordinate = 'A1') + { + // Worksheet reference? + if (strpos($pCoordinate, '!') !== false) { + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); 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) { - $pCoordinate = $namedRange->getRange(); - if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) { - if (!$namedRange->getLocalOnly()) { - return $namedRange->getWorksheet()->cellExists($pCoordinate); - } else { - throw new PHPExcel_Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); - } - } - } - else { return false; } - } + // 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) { + $pCoordinate = $namedRange->getRange(); + if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) { + if (!$namedRange->getLocalOnly()) { + return $namedRange->getWorksheet()->cellExists($pCoordinate); + } else { + throw new PHPExcel_Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); + } + } + } + else { return false; } + } - // Uppercase coordinate - $pCoordinate = strtoupper($pCoordinate); + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); - } elseif (strpos($pCoordinate,'$') !== false) { - throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); - } else { - // Coordinates - $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); + } elseif (strpos($pCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } else { + // Coordinates + $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); - // Cell exists? - return $this->_cellCollection->isDataSet($pCoordinate); - } - } + // Cell exists? + return $this->_cellCollection->isDataSet($pCoordinate); + } + } - /** - * Cell at a specific coordinate by using numeric cell coordinates exists? - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @return boolean - */ - public function cellExistsByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->cellExists(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } + /** + * Cell at a specific coordinate by using numeric cell coordinates exists? + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @return boolean + */ + public function cellExistsByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->cellExists(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } - /** - * Get row dimension at a specific row - * - * @param int $pRow Numeric index of the row - * @return PHPExcel_Worksheet_RowDimension - */ - public function getRowDimension($pRow = 1) - { - // Found - $found = null; + /** + * Get row dimension at a specific row + * + * @param int $pRow Numeric index of the row + * @return PHPExcel_Worksheet_RowDimension + */ + public function getRowDimension($pRow = 1) + { + // Found + $found = null; - // Get row dimension - if (!isset($this->_rowDimensions[$pRow])) { - $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); + // Get row dimension + if (!isset($this->_rowDimensions[$pRow])) { + $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); - $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); - } - return $this->_rowDimensions[$pRow]; - } + $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); + } + return $this->_rowDimensions[$pRow]; + } - /** - * Get column dimension at a specific column - * - * @param string $pColumn String index of the column - * @return PHPExcel_Worksheet_ColumnDimension - */ - public function getColumnDimension($pColumn = 'A') - { - // Uppercase coordinate - $pColumn = strtoupper($pColumn); + /** + * Get column dimension at a specific column + * + * @param string $pColumn String index of the column + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getColumnDimension($pColumn = 'A') + { + // Uppercase coordinate + $pColumn = strtoupper($pColumn); - // Fetch dimensions - if (!isset($this->_columnDimensions[$pColumn])) { - $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); + // Fetch dimensions + if (!isset($this->_columnDimensions[$pColumn])) { + $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); - if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) - $this->_cachedHighestColumn = $pColumn; - } - return $this->_columnDimensions[$pColumn]; - } + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) + $this->_cachedHighestColumn = $pColumn; + } + return $this->_columnDimensions[$pColumn]; + } - /** - * Get column dimension at a specific column by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @return PHPExcel_Worksheet_ColumnDimension - */ - public function getColumnDimensionByColumn($pColumn = 0) - { - return $this->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($pColumn)); - } + /** + * Get column dimension at a specific column by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getColumnDimensionByColumn($pColumn = 0) + { + return $this->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($pColumn)); + } - /** - * Get styles - * - * @return PHPExcel_Style[] - */ - public function getStyles() - { - return $this->_styles; - } + /** + * Get styles + * + * @return PHPExcel_Style[] + */ + public function getStyles() + { + return $this->_styles; + } - /** - * Get default style of workbook. - * - * @deprecated - * @return PHPExcel_Style - * @throws PHPExcel_Exception - */ - public function getDefaultStyle() - { - return $this->_parent->getDefaultStyle(); - } + /** + * Get default style of workbook. + * + * @deprecated + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getDefaultStyle() + { + return $this->_parent->getDefaultStyle(); + } - /** - * Set default style - should only be used by PHPExcel_IReader implementations! - * - * @deprecated - * @param PHPExcel_Style $pValue - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setDefaultStyle(PHPExcel_Style $pValue) - { - $this->_parent->getDefaultStyle()->applyFromArray(array( - 'font' => array( - 'name' => $pValue->getFont()->getName(), - 'size' => $pValue->getFont()->getSize(), - ), - )); - return $this; - } + /** + * Set default style - should only be used by PHPExcel_IReader implementations! + * + * @deprecated + * @param PHPExcel_Style $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setDefaultStyle(PHPExcel_Style $pValue) + { + $this->_parent->getDefaultStyle()->applyFromArray(array( + 'font' => array( + 'name' => $pValue->getFont()->getName(), + 'size' => $pValue->getFont()->getSize(), + ), + )); + return $this; + } - /** - * Get style for cell - * - * @param string $pCellCoordinate Cell coordinate to get style for - * @return PHPExcel_Style - * @throws PHPExcel_Exception - */ - public function getStyle($pCellCoordinate = 'A1') - { - // set this sheet as active - $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); + /** + * Get style for cell + * + * @param string $pCellCoordinate Cell coordinate to get style for + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getStyle($pCellCoordinate = 'A1') + { + // set this sheet as active + $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); - // set cell coordinate as active - $this->setSelectedCells($pCellCoordinate); + // set cell coordinate as active + $this->setSelectedCells($pCellCoordinate); - return $this->_parent->getCellXfSupervisor(); - } + return $this->_parent->getCellXfSupervisor(); + } - /** - * Get conditional styles for a cell - * - * @param string $pCoordinate - * @return PHPExcel_Style_Conditional[] - */ - public function getConditionalStyles($pCoordinate = 'A1') - { - if (!isset($this->_conditionalStylesCollection[$pCoordinate])) { - $this->_conditionalStylesCollection[$pCoordinate] = array(); - } - return $this->_conditionalStylesCollection[$pCoordinate]; - } + /** + * Get conditional styles for a cell + * + * @param string $pCoordinate + * @return PHPExcel_Style_Conditional[] + */ + public function getConditionalStyles($pCoordinate = 'A1') + { + if (!isset($this->_conditionalStylesCollection[$pCoordinate])) { + $this->_conditionalStylesCollection[$pCoordinate] = array(); + } + return $this->_conditionalStylesCollection[$pCoordinate]; + } - /** - * Do conditional styles exist for this cell? - * - * @param string $pCoordinate - * @return boolean - */ - public function conditionalStylesExists($pCoordinate = 'A1') - { - if (isset($this->_conditionalStylesCollection[$pCoordinate])) { - return true; - } - return false; - } + /** + * Do conditional styles exist for this cell? + * + * @param string $pCoordinate + * @return boolean + */ + public function conditionalStylesExists($pCoordinate = 'A1') + { + if (isset($this->_conditionalStylesCollection[$pCoordinate])) { + return true; + } + return false; + } - /** - * Removes conditional styles for a cell - * - * @param string $pCoordinate - * @return PHPExcel_Worksheet - */ - public function removeConditionalStyles($pCoordinate = 'A1') - { - unset($this->_conditionalStylesCollection[$pCoordinate]); - return $this; - } + /** + * Removes conditional styles for a cell + * + * @param string $pCoordinate + * @return PHPExcel_Worksheet + */ + public function removeConditionalStyles($pCoordinate = 'A1') + { + unset($this->_conditionalStylesCollection[$pCoordinate]); + return $this; + } - /** - * Get collection of conditional styles - * - * @return array - */ - public function getConditionalStylesCollection() - { - return $this->_conditionalStylesCollection; - } + /** + * Get collection of conditional styles + * + * @return array + */ + public function getConditionalStylesCollection() + { + return $this->_conditionalStylesCollection; + } - /** - * Set conditional styles - * - * @param $pCoordinate string E.g. 'A1' - * @param $pValue PHPExcel_Style_Conditional[] - * @return PHPExcel_Worksheet - */ - public function setConditionalStyles($pCoordinate = 'A1', $pValue) - { - $this->_conditionalStylesCollection[$pCoordinate] = $pValue; - return $this; - } + /** + * Set conditional styles + * + * @param $pCoordinate string E.g. 'A1' + * @param $pValue PHPExcel_Style_Conditional[] + * @return PHPExcel_Worksheet + */ + public function setConditionalStyles($pCoordinate = 'A1', $pValue) + { + $this->_conditionalStylesCollection[$pCoordinate] = $pValue; + return $this; + } - /** - * Get style for cell by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @return PHPExcel_Style - */ - public function getStyleByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->getStyle(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } + /** + * Get style for cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @return PHPExcel_Style + */ + public function getStyleByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->getStyle(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } - /** - * Set shared cell style to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range! - * - * @deprecated - * @param PHPExcel_Style $pSharedCellStyle Cell style to share - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setSharedStyle(PHPExcel_Style $pSharedCellStyle = null, $pRange = '') - { - $this->duplicateStyle($pSharedCellStyle, $pRange); - return $this; - } + /** + * Set shared cell style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @deprecated + * @param PHPExcel_Style $pSharedCellStyle Cell style to share + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSharedStyle(PHPExcel_Style $pSharedCellStyle = null, $pRange = '') + { + $this->duplicateStyle($pSharedCellStyle, $pRange); + return $this; + } - /** - * Duplicate cell style to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range! - * - * @param PHPExcel_Style $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 - */ - public function duplicateStyle(PHPExcel_Style $pCellStyle = null, $pRange = '') - { - // make sure we have a real style and not supervisor - $style = $pCellStyle->getIsSupervisor() ? $pCellStyle->getSharedComponent() : $pCellStyle; + /** + * Duplicate cell style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @param PHPExcel_Style $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 + */ + public function duplicateStyle(PHPExcel_Style $pCellStyle = null, $pRange = '') + { + // make sure we have a real style and not supervisor + $style = $pCellStyle->getIsSupervisor() ? $pCellStyle->getSharedComponent() : $pCellStyle; - // Add the style to the workbook if necessary - $workbook = $this->_parent; - if ($this->_parent->cellXfExists($pCellStyle)) { - // there is already this cell Xf in our collection - $xfIndex = $pCellStyle->getIndex(); - } else { - // we don't have such a cell Xf, need to add - $workbook->addCellXf($pCellStyle); - $xfIndex = $pCellStyle->getIndex(); - } + // Add the style to the workbook if necessary + $workbook = $this->_parent; + if ($this->_parent->cellXfExists($pCellStyle)) { + // there is already this cell Xf in our collection + $xfIndex = $pCellStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($pCellStyle); + $xfIndex = $pCellStyle->getIndex(); + } - // Uppercase coordinate - $pRange = strtoupper($pRange); + // Uppercase coordinate + $pRange = strtoupper($pRange); - // Is it a cell range or a single cell? - $rangeA = ''; - $rangeB = ''; - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } + // Is it a cell range or a single cell? + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } - // Loop through cells and apply styles - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col) . $row)->setXfIndex($xfIndex); - } - } + // Loop through cells and apply styles + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col) . $row)->setXfIndex($xfIndex); + } + } - return $this; - } + return $this; + } - /** - * Duplicate conditional style to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range! - * + /** + * Duplicate conditional style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * * @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 - */ - public function duplicateConditionalStyle(array $pCellStyle = null, $pRange = '') - { - foreach($pCellStyle as $cellStyle) { - if (!($cellStyle instanceof PHPExcel_Style_Conditional)) { - throw new PHPExcel_Exception('Style is not a conditional style'); - } - } + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateConditionalStyle(array $pCellStyle = null, $pRange = '') + { + foreach($pCellStyle as $cellStyle) { + if (!($cellStyle instanceof PHPExcel_Style_Conditional)) { + throw new PHPExcel_Exception('Style is not a conditional style'); + } + } - // Uppercase coordinate - $pRange = strtoupper($pRange); + // Uppercase coordinate + $pRange = strtoupper($pRange); - // Is it a cell range or a single cell? - $rangeA = ''; - $rangeB = ''; - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } + // Is it a cell range or a single cell? + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } - // Loop through cells and apply styles - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $this->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($col) . $row, $pCellStyle); - } - } + // Loop through cells and apply styles + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $this->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($col) . $row, $pCellStyle); + } + } - return $this; - } + return $this; + } - /** - * Duplicate cell style array to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range, - * if they are in the styles array. For example, if you decide to set a range of - * cells to font bold, only include font bold in the styles array. - * - * @deprecated - * @param array $pStyles Array containing style information - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @param boolean $pAdvanced Advanced mode for setting borders. - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function duplicateStyleArray($pStyles = null, $pRange = '', $pAdvanced = true) - { - $this->getStyle($pRange)->applyFromArray($pStyles, $pAdvanced); - return $this; - } + /** + * Duplicate cell style array to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range, + * if they are in the styles array. For example, if you decide to set a range of + * cells to font bold, only include font bold in the styles array. + * + * @deprecated + * @param array $pStyles Array containing style information + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @param boolean $pAdvanced Advanced mode for setting borders. + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateStyleArray($pStyles = null, $pRange = '', $pAdvanced = true) + { + $this->getStyle($pRange)->applyFromArray($pStyles, $pAdvanced); + return $this; + } - /** - * Set break on a cell - * - * @param string $pCell Cell coordinate (e.g. A1) - * @param int $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setBreak($pCell = 'A1', $pBreak = PHPExcel_Worksheet::BREAK_NONE) - { - // Uppercase coordinate - $pCell = strtoupper($pCell); + /** + * Set break on a cell + * + * @param string $pCell Cell coordinate (e.g. A1) + * @param int $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setBreak($pCell = 'A1', $pBreak = PHPExcel_Worksheet::BREAK_NONE) + { + // Uppercase coordinate + $pCell = strtoupper($pCell); - if ($pCell != '') { - $this->_breaks[$pCell] = $pBreak; - } else { - throw new PHPExcel_Exception('No cell coordinate specified.'); - } + if ($pCell != '') { + $this->_breaks[$pCell] = $pBreak; + } else { + throw new PHPExcel_Exception('No cell coordinate specified.'); + } - return $this; - } + return $this; + } - /** - * Set break on a cell by using numeric cell coordinates - * - * @param integer $pColumn Numeric column coordinate of the cell - * @param integer $pRow Numeric row coordinate of the cell - * @param integer $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) - * @return PHPExcel_Worksheet - */ - public function setBreakByColumnAndRow($pColumn = 0, $pRow = 1, $pBreak = PHPExcel_Worksheet::BREAK_NONE) - { - return $this->setBreak(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pBreak); - } + /** + * Set break on a cell by using numeric cell coordinates + * + * @param integer $pColumn Numeric column coordinate of the cell + * @param integer $pRow Numeric row coordinate of the cell + * @param integer $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) + * @return PHPExcel_Worksheet + */ + public function setBreakByColumnAndRow($pColumn = 0, $pRow = 1, $pBreak = PHPExcel_Worksheet::BREAK_NONE) + { + return $this->setBreak(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pBreak); + } - /** - * Get breaks - * - * @return array[] - */ - public function getBreaks() - { - return $this->_breaks; - } + /** + * Get breaks + * + * @return array[] + */ + public function getBreaks() + { + return $this->_breaks; + } - /** - * Set merge on a cell range - * - * @param string $pRange Cell range (e.g. A1:E1) - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function mergeCells($pRange = 'A1:A1') - { - // Uppercase coordinate - $pRange = strtoupper($pRange); + /** + * Set merge on a cell range + * + * @param string $pRange Cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function mergeCells($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); - if (strpos($pRange,':') !== false) { - $this->_mergeCells[$pRange] = $pRange; + if (strpos($pRange,':') !== false) { + $this->_mergeCells[$pRange] = $pRange; - // make sure cells are created + // make sure cells are created - // get the cells in the range - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + // get the cells in the range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); - // create upper left cell if it does not already exist - $upperLeft = $aReferences[0]; - if (!$this->cellExists($upperLeft)) { - $this->getCell($upperLeft)->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); - } + // create upper left cell if it does not already exist + $upperLeft = $aReferences[0]; + if (!$this->cellExists($upperLeft)) { + $this->getCell($upperLeft)->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } - // create or blank out the rest of the cells in the range - $count = count($aReferences); - for ($i = 1; $i < $count; $i++) { - $this->getCell($aReferences[$i])->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); - } + // create or blank out the rest of the cells in the range + $count = count($aReferences); + for ($i = 1; $i < $count; $i++) { + $this->getCell($aReferences[$i])->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } - } else { - throw new PHPExcel_Exception('Merge must be set on a range of cells.'); - } + } else { + throw new PHPExcel_Exception('Merge must be set on a range of cells.'); + } - return $this; - } + return $this; + } - /** - * Set merge on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function mergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->mergeCells($cellRange); - } + /** + * Set merge on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function mergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->mergeCells($cellRange); + } - /** - * Remove merge on a cell range - * - * @param string $pRange Cell range (e.g. A1:E1) - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function unmergeCells($pRange = 'A1:A1') - { - // Uppercase coordinate - $pRange = strtoupper($pRange); + /** + * Remove merge on a cell range + * + * @param string $pRange Cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unmergeCells($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); - if (strpos($pRange,':') !== false) { - if (isset($this->_mergeCells[$pRange])) { - unset($this->_mergeCells[$pRange]); - } else { - throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as merged.'); - } - } else { - throw new PHPExcel_Exception('Merge can only be removed from a range of cells.'); - } + if (strpos($pRange,':') !== false) { + if (isset($this->_mergeCells[$pRange])) { + unset($this->_mergeCells[$pRange]); + } else { + throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as merged.'); + } + } else { + throw new PHPExcel_Exception('Merge can only be removed from a range of cells.'); + } - return $this; - } + return $this; + } - /** - * Remove merge on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function unmergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->unmergeCells($cellRange); - } + /** + * Remove merge on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unmergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->unmergeCells($cellRange); + } - /** - * Get merge cells array. - * - * @return array[] - */ - public function getMergeCells() - { - return $this->_mergeCells; - } + /** + * Get merge cells array. + * + * @return array[] + */ + public function getMergeCells() + { + return $this->_mergeCells; + } - /** - * Set merge cells array for the entire sheet. Use instead mergeCells() to merge - * a single cell range. - * - * @param array - */ - public function setMergeCells($pValue = array()) - { - $this->_mergeCells = $pValue; + /** + * Set merge cells array for the entire sheet. Use instead mergeCells() to merge + * a single cell range. + * + * @param array + */ + public function setMergeCells($pValue = array()) + { + $this->_mergeCells = $pValue; - return $this; - } + return $this; + } - /** - * Set protection on a cell range - * - * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) - * @param string $pPassword Password to unlock the protection - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function protectCells($pRange = 'A1', $pPassword = '', $pAlreadyHashed = false) - { - // Uppercase coordinate - $pRange = strtoupper($pRange); + /** + * Set protection on a cell range + * + * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function protectCells($pRange = 'A1', $pPassword = '', $pAlreadyHashed = false) + { + // Uppercase coordinate + $pRange = strtoupper($pRange); - if (!$pAlreadyHashed) { - $pPassword = PHPExcel_Shared_PasswordHasher::hashPassword($pPassword); - } - $this->_protectedCells[$pRange] = $pPassword; + if (!$pAlreadyHashed) { + $pPassword = PHPExcel_Shared_PasswordHasher::hashPassword($pPassword); + } + $this->_protectedCells[$pRange] = $pPassword; - return $this; - } + return $this; + } - /** - * Set protection on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @param string $pPassword Password to unlock the protection - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function protectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->protectCells($cellRange, $pPassword, $pAlreadyHashed); - } + /** + * Set protection on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function protectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->protectCells($cellRange, $pPassword, $pAlreadyHashed); + } - /** - * Remove protection on a cell range - * - * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function unprotectCells($pRange = 'A1') - { - // Uppercase coordinate - $pRange = strtoupper($pRange); + /** + * Remove protection on a cell range + * + * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unprotectCells($pRange = 'A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); - if (isset($this->_protectedCells[$pRange])) { - unset($this->_protectedCells[$pRange]); - } else { - throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as protected.'); - } - return $this; - } + if (isset($this->_protectedCells[$pRange])) { + unset($this->_protectedCells[$pRange]); + } else { + throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as protected.'); + } + return $this; + } - /** - * Remove protection on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @param string $pPassword Password to unlock the protection - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function unprotectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->unprotectCells($cellRange, $pPassword, $pAlreadyHashed); - } + /** + * Remove protection on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unprotectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->unprotectCells($cellRange, $pPassword, $pAlreadyHashed); + } - /** - * Get protected cells - * - * @return array[] - */ - public function getProtectedCells() - { - return $this->_protectedCells; - } + /** + * Get protected cells + * + * @return array[] + */ + public function getProtectedCells() + { + return $this->_protectedCells; + } - /** - * Get Autofilter - * - * @return PHPExcel_Worksheet_AutoFilter - */ - public function getAutoFilter() - { - return $this->_autoFilter; - } + /** + * Get Autofilter + * + * @return PHPExcel_Worksheet_AutoFilter + */ + public function getAutoFilter() + { + return $this->_autoFilter; + } - /** - * Set AutoFilter - * - * @param PHPExcel_Worksheet_AutoFilter|string $pValue - * A simple string containing a Cell range like 'A1:E10' is permitted for backward compatibility - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setAutoFilter($pValue) - { - if (is_string($pValue)) { - $this->_autoFilter->setRange($pValue); - } elseif(is_object($pValue) && ($pValue instanceof PHPExcel_Worksheet_AutoFilter)) { - $this->_autoFilter = $pValue; - } - return $this; - } + /** + * Set AutoFilter + * + * @param PHPExcel_Worksheet_AutoFilter|string $pValue + * A simple string containing a Cell range like 'A1:E10' is permitted for backward compatibility + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setAutoFilter($pValue) + { + if (is_string($pValue)) { + $this->_autoFilter->setRange($pValue); + } elseif(is_object($pValue) && ($pValue instanceof PHPExcel_Worksheet_AutoFilter)) { + $this->_autoFilter = $pValue; + } + return $this; + } - /** - * Set Autofilter Range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the second cell - * @param int $pRow2 Numeric row coordinate of the second cell - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setAutoFilterByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) - { - return $this->setAutoFilter( - PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 - . ':' . - PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2 - ); - } + /** + * Set Autofilter Range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the second cell + * @param int $pRow2 Numeric row coordinate of the second cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setAutoFilterByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + return $this->setAutoFilter( + PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 + . ':' . + PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2 + ); + } /** * Remove autofilter @@ -1901,914 +1896,914 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function removeAutoFilter() { - $this->_autoFilter->setRange(NULL); - return $this; + $this->_autoFilter->setRange(NULL); + return $this; } - /** - * Get Freeze Pane - * - * @return string - */ - public function getFreezePane() - { - return $this->_freezePane; - } + /** + * Get Freeze Pane + * + * @return string + */ + public function getFreezePane() + { + return $this->_freezePane; + } - /** - * Freeze Pane - * - * @param string $pCell Cell (i.e. A2) - * Examples: - * A2 will freeze the rows above cell A2 (i.e row 1) - * B1 will freeze the columns to the left of cell B1 (i.e column A) - * B2 will freeze the rows above and to the left of cell A2 - * (i.e row 1 and column A) - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function freezePane($pCell = '') - { - // Uppercase coordinate - $pCell = strtoupper($pCell); + /** + * Freeze Pane + * + * @param string $pCell Cell (i.e. A2) + * Examples: + * A2 will freeze the rows above cell A2 (i.e row 1) + * B1 will freeze the columns to the left of cell B1 (i.e column A) + * B2 will freeze the rows above and to the left of cell A2 + * (i.e row 1 and column A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function freezePane($pCell = '') + { + // Uppercase coordinate + $pCell = strtoupper($pCell); - if (strpos($pCell,':') === false && strpos($pCell,',') === false) { - $this->_freezePane = $pCell; - } else { - throw new PHPExcel_Exception('Freeze pane can not be set on a range of cells.'); - } - return $this; - } + if (strpos($pCell,':') === false && strpos($pCell,',') === false) { + $this->_freezePane = $pCell; + } else { + throw new PHPExcel_Exception('Freeze pane can not be set on a range of cells.'); + } + return $this; + } - /** - * Freeze Pane by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function freezePaneByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->freezePane(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } + /** + * Freeze Pane by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function freezePaneByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->freezePane(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } - /** - * Unfreeze Pane - * - * @return PHPExcel_Worksheet - */ - public function unfreezePane() - { - return $this->freezePane(''); - } + /** + * Unfreeze Pane + * + * @return PHPExcel_Worksheet + */ + public function unfreezePane() + { + return $this->freezePane(''); + } - /** - * Insert a new row, updating all possible related data - * - * @param int $pBefore Insert before this one - * @param int $pNumRows Number of rows to insert - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function insertNewRowBefore($pBefore = 1, $pNumRows = 1) { - if ($pBefore >= 1) { - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore('A' . $pBefore, 0, $pNumRows, $this); - } else { - throw new PHPExcel_Exception("Rows can only be inserted before at least row 1."); - } - return $this; - } + /** + * Insert a new row, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumRows Number of rows to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewRowBefore($pBefore = 1, $pNumRows = 1) { + if ($pBefore >= 1) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . $pBefore, 0, $pNumRows, $this); + } else { + throw new PHPExcel_Exception("Rows can only be inserted before at least row 1."); + } + return $this; + } - /** - * Insert a new column, updating all possible related data - * - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function insertNewColumnBefore($pBefore = 'A', $pNumCols = 1) { - if (!is_numeric($pBefore)) { - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore($pBefore . '1', $pNumCols, 0, $this); - } else { - throw new PHPExcel_Exception("Column references should not be numeric."); - } - return $this; - } + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewColumnBefore($pBefore = 'A', $pNumCols = 1) { + if (!is_numeric($pBefore)) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pBefore . '1', $pNumCols, 0, $this); + } else { + throw new PHPExcel_Exception("Column references should not be numeric."); + } + return $this; + } - /** - * Insert a new column, updating all possible related data - * - * @param int $pBefore Insert before this one (numeric column coordinate of the cell) - * @param int $pNumCols Number of columns to insert - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function insertNewColumnBeforeByIndex($pBefore = 0, $pNumCols = 1) { - if ($pBefore >= 0) { - return $this->insertNewColumnBefore(PHPExcel_Cell::stringFromColumnIndex($pBefore), $pNumCols); - } else { - throw new PHPExcel_Exception("Columns can only be inserted before at least column A (0)."); - } - } + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one (numeric column coordinate of the cell) + * @param int $pNumCols Number of columns to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewColumnBeforeByIndex($pBefore = 0, $pNumCols = 1) { + if ($pBefore >= 0) { + return $this->insertNewColumnBefore(PHPExcel_Cell::stringFromColumnIndex($pBefore), $pNumCols); + } else { + throw new PHPExcel_Exception("Columns can only be inserted before at least column A (0)."); + } + } - /** - * Delete a row, updating all possible related data - * - * @param int $pRow Remove starting with this one - * @param int $pNumRows Number of rows to remove - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function removeRow($pRow = 1, $pNumRows = 1) { - if ($pRow >= 1) { - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); - } else { - throw new PHPExcel_Exception("Rows to be deleted should at least start from row 1."); - } - return $this; - } + /** + * Delete a row, updating all possible related data + * + * @param int $pRow Remove starting with this one + * @param int $pNumRows Number of rows to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeRow($pRow = 1, $pNumRows = 1) { + if ($pRow >= 1) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); + } else { + throw new PHPExcel_Exception("Rows to be deleted should at least start from row 1."); + } + return $this; + } - /** - * Remove a column, updating all possible related data - * - * @param int $pColumn Remove starting with this one - * @param int $pNumCols Number of columns to remove - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function removeColumn($pColumn = 'A', $pNumCols = 1) { - if (!is_numeric($pColumn)) { - $pColumn = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($pColumn) - 1 + $pNumCols); - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); - } else { - throw new PHPExcel_Exception("Column references should not be numeric."); - } - return $this; - } + /** + * Remove a column, updating all possible related data + * + * @param int $pColumn Remove starting with this one + * @param int $pNumCols Number of columns to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeColumn($pColumn = 'A', $pNumCols = 1) { + if (!is_numeric($pColumn)) { + $pColumn = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($pColumn) - 1 + $pNumCols); + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); + } else { + throw new PHPExcel_Exception("Column references should not be numeric."); + } + return $this; + } - /** - * Remove a column, updating all possible related data - * - * @param int $pColumn Remove starting with this one (numeric column coordinate of the cell) - * @param int $pNumCols Number of columns to remove - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function removeColumnByIndex($pColumn = 0, $pNumCols = 1) { - if ($pColumn >= 0) { - return $this->removeColumn(PHPExcel_Cell::stringFromColumnIndex($pColumn), $pNumCols); - } else { - throw new PHPExcel_Exception("Columns to be deleted should at least start from column 0"); - } - } + /** + * Remove a column, updating all possible related data + * + * @param int $pColumn Remove starting with this one (numeric column coordinate of the cell) + * @param int $pNumCols Number of columns to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeColumnByIndex($pColumn = 0, $pNumCols = 1) { + if ($pColumn >= 0) { + return $this->removeColumn(PHPExcel_Cell::stringFromColumnIndex($pColumn), $pNumCols); + } else { + throw new PHPExcel_Exception("Columns to be deleted should at least start from column 0"); + } + } - /** - * Show gridlines? - * - * @return boolean - */ - public function getShowGridlines() { - return $this->_showGridlines; - } + /** + * Show gridlines? + * + * @return boolean + */ + public function getShowGridlines() { + return $this->_showGridlines; + } - /** - * Set show gridlines - * - * @param boolean $pValue Show gridlines (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowGridlines($pValue = false) { - $this->_showGridlines = $pValue; - return $this; - } + /** + * Set show gridlines + * + * @param boolean $pValue Show gridlines (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowGridlines($pValue = false) { + $this->_showGridlines = $pValue; + return $this; + } - /** - * Print gridlines? - * - * @return boolean - */ - public function getPrintGridlines() { - return $this->_printGridlines; - } + /** + * Print gridlines? + * + * @return boolean + */ + public function getPrintGridlines() { + return $this->_printGridlines; + } - /** - * Set print gridlines - * - * @param boolean $pValue Print gridlines (true/false) - * @return PHPExcel_Worksheet - */ - public function setPrintGridlines($pValue = false) { - $this->_printGridlines = $pValue; - return $this; - } + /** + * Set print gridlines + * + * @param boolean $pValue Print gridlines (true/false) + * @return PHPExcel_Worksheet + */ + public function setPrintGridlines($pValue = false) { + $this->_printGridlines = $pValue; + return $this; + } - /** - * Show row and column headers? - * - * @return boolean - */ - public function getShowRowColHeaders() { - return $this->_showRowColHeaders; - } + /** + * Show row and column headers? + * + * @return boolean + */ + public function getShowRowColHeaders() { + return $this->_showRowColHeaders; + } - /** - * Set show row and column headers - * - * @param boolean $pValue Show row and column headers (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowRowColHeaders($pValue = false) { - $this->_showRowColHeaders = $pValue; - return $this; - } + /** + * Set show row and column headers + * + * @param boolean $pValue Show row and column headers (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowRowColHeaders($pValue = false) { + $this->_showRowColHeaders = $pValue; + return $this; + } - /** - * Show summary below? (Row/Column outlining) - * - * @return boolean - */ - public function getShowSummaryBelow() { - return $this->_showSummaryBelow; - } + /** + * Show summary below? (Row/Column outlining) + * + * @return boolean + */ + public function getShowSummaryBelow() { + return $this->_showSummaryBelow; + } - /** - * Set show summary below - * - * @param boolean $pValue Show summary below (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowSummaryBelow($pValue = true) { - $this->_showSummaryBelow = $pValue; - return $this; - } + /** + * Set show summary below + * + * @param boolean $pValue Show summary below (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowSummaryBelow($pValue = true) { + $this->_showSummaryBelow = $pValue; + return $this; + } - /** - * Show summary right? (Row/Column outlining) - * - * @return boolean - */ - public function getShowSummaryRight() { - return $this->_showSummaryRight; - } + /** + * Show summary right? (Row/Column outlining) + * + * @return boolean + */ + public function getShowSummaryRight() { + return $this->_showSummaryRight; + } - /** - * Set show summary right - * - * @param boolean $pValue Show summary right (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowSummaryRight($pValue = true) { - $this->_showSummaryRight = $pValue; - return $this; - } + /** + * Set show summary right + * + * @param boolean $pValue Show summary right (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowSummaryRight($pValue = true) { + $this->_showSummaryRight = $pValue; + return $this; + } - /** - * Get comments - * - * @return PHPExcel_Comment[] - */ - public function getComments() - { - return $this->_comments; - } + /** + * Get comments + * + * @return PHPExcel_Comment[] + */ + public function getComments() + { + return $this->_comments; + } - /** - * Set comments array for the entire sheet. - * + /** + * Set comments array for the entire sheet. + * * @param array of PHPExcel_Comment - * @return PHPExcel_Worksheet - */ - public function setComments($pValue = array()) - { - $this->_comments = $pValue; + * @return PHPExcel_Worksheet + */ + public function setComments($pValue = array()) + { + $this->_comments = $pValue; - return $this; - } + return $this; + } - /** - * Get comment for cell - * - * @param string $pCellCoordinate Cell coordinate to get comment for - * @return PHPExcel_Comment - * @throws PHPExcel_Exception - */ - public function getComment($pCellCoordinate = 'A1') - { - // Uppercase coordinate - $pCellCoordinate = strtoupper($pCellCoordinate); + /** + * Get comment for cell + * + * @param string $pCellCoordinate Cell coordinate to get comment for + * @return PHPExcel_Comment + * @throws PHPExcel_Exception + */ + public function getComment($pCellCoordinate = 'A1') + { + // Uppercase coordinate + $pCellCoordinate = strtoupper($pCellCoordinate); - if (strpos($pCellCoordinate,':') !== false || strpos($pCellCoordinate,',') !== false) { - throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells.'); - } else if (strpos($pCellCoordinate,'$') !== false) { - throw new PHPExcel_Exception('Cell coordinate string must not be absolute.'); - } else if ($pCellCoordinate == '') { - throw new PHPExcel_Exception('Cell coordinate can not be zero-length string.'); - } else { - // Check if we already have a comment for this cell. - // If not, create a new comment. - if (isset($this->_comments[$pCellCoordinate])) { - return $this->_comments[$pCellCoordinate]; - } else { - $newComment = new PHPExcel_Comment(); - $this->_comments[$pCellCoordinate] = $newComment; - return $newComment; - } - } - } + if (strpos($pCellCoordinate,':') !== false || strpos($pCellCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells.'); + } else if (strpos($pCellCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate string must not be absolute.'); + } else if ($pCellCoordinate == '') { + throw new PHPExcel_Exception('Cell coordinate can not be zero-length string.'); + } else { + // Check if we already have a comment for this cell. + // If not, create a new comment. + if (isset($this->_comments[$pCellCoordinate])) { + return $this->_comments[$pCellCoordinate]; + } else { + $newComment = new PHPExcel_Comment(); + $this->_comments[$pCellCoordinate] = $newComment; + return $newComment; + } + } + } - /** - * Get comment for cell by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @return PHPExcel_Comment - */ - public function getCommentByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->getComment(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } + /** + * Get comment for cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @return PHPExcel_Comment + */ + public function getCommentByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->getComment(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } - /** - * Get selected cell - * - * @deprecated - * @return string - */ - public function getSelectedCell() - { - return $this->getSelectedCells(); - } + /** + * Get selected cell + * + * @deprecated + * @return string + */ + public function getSelectedCell() + { + return $this->getSelectedCells(); + } - /** - * Get active cell - * - * @return string Example: 'A1' - */ - public function getActiveCell() - { - return $this->_activeCell; - } + /** + * Get active cell + * + * @return string Example: 'A1' + */ + public function getActiveCell() + { + return $this->_activeCell; + } - /** - * Get selected cells - * - * @return string - */ - public function getSelectedCells() - { - return $this->_selectedCells; - } + /** + * Get selected cells + * + * @return string + */ + public function getSelectedCells() + { + return $this->_selectedCells; + } - /** - * Selected cell - * - * @param string $pCoordinate Cell (i.e. A1) - * @return PHPExcel_Worksheet - */ - public function setSelectedCell($pCoordinate = 'A1') - { - return $this->setSelectedCells($pCoordinate); - } + /** + * Selected cell + * + * @param string $pCoordinate Cell (i.e. A1) + * @return PHPExcel_Worksheet + */ + public function setSelectedCell($pCoordinate = 'A1') + { + return $this->setSelectedCells($pCoordinate); + } - /** - * Select a range of cells. - * - * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setSelectedCells($pCoordinate = 'A1') - { - // Uppercase coordinate - $pCoordinate = strtoupper($pCoordinate); + /** + * Select a range of cells. + * + * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSelectedCells($pCoordinate = 'A1') + { + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); - // Convert 'A' to 'A:A' - $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); + // Convert 'A' to 'A:A' + $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); - // Convert '1' to '1:1' - $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); + // Convert '1' to '1:1' + $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); - // Convert 'A:C' to 'A1:C1048576' - $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); + // Convert 'A:C' to 'A1:C1048576' + $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); - // Convert '1:3' to 'A1:XFD3' - $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); + // Convert '1:3' to 'A1:XFD3' + $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); - $this->_activeCell = $first[0]; - } else { - $this->_activeCell = $pCoordinate; - } - $this->_selectedCells = $pCoordinate; - return $this; - } + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); + $this->_activeCell = $first[0]; + } else { + $this->_activeCell = $pCoordinate; + } + $this->_selectedCells = $pCoordinate; + return $this; + } - /** - * Selected cell by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } + /** + * Selected cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } - /** - * Get right-to-left - * - * @return boolean - */ - public function getRightToLeft() { - return $this->_rightToLeft; - } + /** + * Get right-to-left + * + * @return boolean + */ + public function getRightToLeft() { + return $this->_rightToLeft; + } - /** - * Set right-to-left - * - * @param boolean $value Right-to-left true/false - * @return PHPExcel_Worksheet - */ - public function setRightToLeft($value = false) { - $this->_rightToLeft = $value; - return $this; - } + /** + * Set right-to-left + * + * @param boolean $value Right-to-left true/false + * @return PHPExcel_Worksheet + */ + public function setRightToLeft($value = false) { + $this->_rightToLeft = $value; + return $this; + } - /** - * Fill worksheet from values in array - * - * @param array $source Source array - * @param mixed $nullValue Value in source array that stands for blank cell - * @param string $startCell Insert array starting from this cell address as the top left coordinate - * @param boolean $strictNullComparison Apply strict comparison when testing for null values in the array - * @throws PHPExcel_Exception - * @return PHPExcel_Worksheet - */ - public function fromArray($source = null, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) { - if (is_array($source)) { - // Convert a 1-D array to 2-D (for ease of looping) - if (!is_array(end($source))) { - $source = array($source); - } + /** + * Fill worksheet from values in array + * + * @param array $source Source array + * @param mixed $nullValue Value in source array that stands for blank cell + * @param string $startCell Insert array starting from this cell address as the top left coordinate + * @param boolean $strictNullComparison Apply strict comparison when testing for null values in the array + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function fromArray($source = null, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) { + if (is_array($source)) { + // Convert a 1-D array to 2-D (for ease of looping) + if (!is_array(end($source))) { + $source = array($source); + } - // start coordinate - list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($startCell); + // start coordinate + list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($startCell); - // Loop through $source - foreach ($source as $rowData) { - $currentColumn = $startColumn; - foreach($rowData as $cellValue) { - if ($strictNullComparison) { - if ($cellValue !== $nullValue) { - // Set cell value - $this->getCell($currentColumn . $startRow)->setValue($cellValue); - } - } else { - if ($cellValue != $nullValue) { - // Set cell value - $this->getCell($currentColumn . $startRow)->setValue($cellValue); - } - } - ++$currentColumn; - } - ++$startRow; - } - } else { - throw new PHPExcel_Exception("Parameter \$source should be an array."); - } - return $this; - } + // Loop through $source + foreach ($source as $rowData) { + $currentColumn = $startColumn; + foreach($rowData as $cellValue) { + if ($strictNullComparison) { + if ($cellValue !== $nullValue) { + // Set cell value + $this->getCell($currentColumn . $startRow)->setValue($cellValue); + } + } else { + if ($cellValue != $nullValue) { + // Set cell value + $this->getCell($currentColumn . $startRow)->setValue($cellValue); + } + } + ++$currentColumn; + } + ++$startRow; + } + } else { + throw new PHPExcel_Exception("Parameter \$source should be an array."); + } + return $this; + } - /** - * Create array from a range of cells - * - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist - * @param boolean $calculateFormulas Should formulas be calculated? - * @param boolean $formatData Should formatting be applied to cell values? - * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @return array - */ + /** + * Create array from a range of cells + * + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * 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) { - // Returnvalue - $returnValue = array(); - // Identify the range that we need to extract from the worksheet - list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange); - $minCol = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] -1); - $minRow = $rangeStart[1]; - $maxCol = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] -1); - $maxRow = $rangeEnd[1]; + // Returnvalue + $returnValue = array(); + // Identify the range that we need to extract from the worksheet + list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange); + $minCol = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] -1); + $minRow = $rangeStart[1]; + $maxCol = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] -1); + $maxRow = $rangeEnd[1]; - $maxCol++; - // Loop through rows - $r = -1; - for ($row = $minRow; $row <= $maxRow; ++$row) { - $rRef = ($returnCellRef) ? $row : ++$r; - $c = -1; - // Loop through columns in the current row - for ($col = $minCol; $col != $maxCol; ++$col) { - $cRef = ($returnCellRef) ? $col : ++$c; - // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen - // so we test and retrieve directly against _cellCollection - if ($this->_cellCollection->isDataSet($col.$row)) { - // Cell exists - $cell = $this->_cellCollection->getCacheData($col.$row); - if ($cell->getValue() !== null) { - if ($cell->getValue() instanceof PHPExcel_RichText) { - $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); - } else { - if ($calculateFormulas) { - $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); - } else { - $returnValue[$rRef][$cRef] = $cell->getValue(); - } - } + $maxCol++; + // Loop through rows + $r = -1; + for ($row = $minRow; $row <= $maxRow; ++$row) { + $rRef = ($returnCellRef) ? $row : ++$r; + $c = -1; + // Loop through columns in the current row + for ($col = $minCol; $col != $maxCol; ++$col) { + $cRef = ($returnCellRef) ? $col : ++$c; + // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen + // so we test and retrieve directly against _cellCollection + if ($this->_cellCollection->isDataSet($col.$row)) { + // Cell exists + $cell = $this->_cellCollection->getCacheData($col.$row); + if ($cell->getValue() !== null) { + if ($cell->getValue() instanceof PHPExcel_RichText) { + $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); + } else { + if ($calculateFormulas) { + $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); + } else { + $returnValue[$rRef][$cRef] = $cell->getValue(); + } + } - if ($formatData) { - $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); + if ($formatData) { + $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( $returnValue[$rRef][$cRef], $style->getNumberFormat()->getFormatCode() ); - } - } else { - // Cell holds a NULL - $returnValue[$rRef][$cRef] = $nullValue; - } - } else { - // Cell doesn't exist - $returnValue[$rRef][$cRef] = $nullValue; - } - } - } + } + } else { + // Cell holds a NULL + $returnValue[$rRef][$cRef] = $nullValue; + } + } else { + // Cell doesn't exist + $returnValue[$rRef][$cRef] = $nullValue; + } + } + } - // Return - return $returnValue; - } + // Return + return $returnValue; + } - /** - * Create array from a range of cells - * - * @param string $pNamedRange Name of the Named Range - * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist - * @param boolean $calculateFormulas Should formulas be calculated? - * @param boolean $formatData Should formatting be applied to cell values? - * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @return array - * @throws PHPExcel_Exception - */ + /** + * Create array from a range of cells + * + * @param string $pNamedRange Name of the Named Range + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + * @throws PHPExcel_Exception + */ public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { - $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); - if ($namedRange !== NULL) { - $pWorkSheet = $namedRange->getWorksheet(); - $pCellRange = $namedRange->getRange(); + $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); + if ($namedRange !== NULL) { + $pWorkSheet = $namedRange->getWorksheet(); + $pCellRange = $namedRange->getRange(); return $pWorkSheet->rangeToArray( $pCellRange, $nullValue, $calculateFormulas, $formatData, $returnCellRef); - } + } - throw new PHPExcel_Exception('Named Range '.$pNamedRange.' does not exist.'); - } + throw new PHPExcel_Exception('Named Range '.$pNamedRange.' does not exist.'); + } - /** - * Create array from worksheet - * - * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist - * @param boolean $calculateFormulas Should formulas be calculated? - * @param boolean $formatData Should formatting be applied to cell values? - * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @return array - */ + /** + * Create array from worksheet + * + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * 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) { - // Garbage collect... - $this->garbageCollect(); + // Garbage collect... + $this->garbageCollect(); - // Identify the range that we need to extract from the worksheet - $maxCol = $this->getHighestColumn(); - $maxRow = $this->getHighestRow(); - // Return + // Identify the range that we need to extract from the worksheet + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + // Return return $this->rangeToArray( 'A1:'.$maxCol.$maxRow, $nullValue, $calculateFormulas, $formatData, $returnCellRef); - } + } - /** - * Get row iterator - * + /** + * Get row iterator + * * @param integer $startRow The row number at which to start iterating - * @return PHPExcel_Worksheet_RowIterator - */ + * @return PHPExcel_Worksheet_RowIterator + */ public function getRowIterator($startRow = 1) { - return new PHPExcel_Worksheet_RowIterator($this,$startRow); - } + return new PHPExcel_Worksheet_RowIterator($this,$startRow); + } - /** - * Run PHPExcel garabage collector. - * - * @return PHPExcel_Worksheet - */ + /** + * Run PHPExcel garabage collector. + * + * @return PHPExcel_Worksheet + */ public function garbageCollect() { - // Flush cache - $this->_cellCollection->getCacheData('A1'); - // Build a reference table from images -// $imageCoordinates = array(); -// $iterator = $this->getDrawingCollection()->getIterator(); -// while ($iterator->valid()) { -// $imageCoordinates[$iterator->current()->getCoordinates()] = true; + // Flush cache + $this->_cellCollection->getCacheData('A1'); + // Build a reference table from images +// $imageCoordinates = array(); +// $iterator = $this->getDrawingCollection()->getIterator(); +// while ($iterator->valid()) { +// $imageCoordinates[$iterator->current()->getCoordinates()] = true; // -// $iterator->next(); -// } +// $iterator->next(); +// } // - // Lookup highest column and highest row if cells are cleaned - $colRow = $this->_cellCollection->getHighestRowAndColumn(); - $highestRow = $colRow['row']; - $highestColumn = PHPExcel_Cell::columnIndexFromString($colRow['column']); + // Lookup highest column and highest row if cells are cleaned + $colRow = $this->_cellCollection->getHighestRowAndColumn(); + $highestRow = $colRow['row']; + $highestColumn = PHPExcel_Cell::columnIndexFromString($colRow['column']); - // Loop through column dimensions - foreach ($this->_columnDimensions as $dimension) { - $highestColumn = max($highestColumn,PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())); - } + // Loop through column dimensions + foreach ($this->_columnDimensions as $dimension) { + $highestColumn = max($highestColumn,PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())); + } - // Loop through row dimensions - foreach ($this->_rowDimensions as $dimension) { - $highestRow = max($highestRow,$dimension->getRowIndex()); - } + // Loop through row dimensions + foreach ($this->_rowDimensions as $dimension) { + $highestRow = max($highestRow,$dimension->getRowIndex()); + } - // Cache values - if ($highestColumn < 0) { - $this->_cachedHighestColumn = 'A'; - } else { - $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); - } - $this->_cachedHighestRow = $highestRow; + // Cache values + if ($highestColumn < 0) { + $this->_cachedHighestColumn = 'A'; + } else { + $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); + } + $this->_cachedHighestRow = $highestRow; - // Return - return $this; - } + // Return + return $this; + } - /** - * Get hash code - * - * @return string Hash code - */ + /** + * Get hash code + * + * @return string Hash code + */ public function getHashCode() { - if ($this->_dirty) { - $this->_hash = md5( $this->_title . - $this->_autoFilter . - ($this->_protection->isProtectionEnabled() ? 't' : 'f') . - __CLASS__ - ); - $this->_dirty = false; - } - return $this->_hash; - } + if ($this->_dirty) { + $this->_hash = md5( $this->_title . + $this->_autoFilter . + ($this->_protection->isProtectionEnabled() ? 't' : 'f') . + __CLASS__ + ); + $this->_dirty = false; + } + return $this->_hash; + } - /** - * Extract worksheet title from range. - * - * Example: extractSheetTitle("testSheet!A1") ==> 'A1' - * Example: extractSheetTitle("'testSheet 1'!A1", true) ==> array('testSheet 1', 'A1'); - * - * @param string $pRange Range to extract title from - * @param bool $returnRange Return range? (see example) - * @return mixed - */ + /** + * Extract worksheet title from range. + * + * Example: extractSheetTitle("testSheet!A1") ==> 'A1' + * Example: extractSheetTitle("'testSheet 1'!A1", true) ==> array('testSheet 1', 'A1'); + * + * @param string $pRange Range to extract title from + * @param bool $returnRange Return range? (see example) + * @return mixed + */ public static function extractSheetTitle($pRange, $returnRange = false) { - // Sheet title included? - if (($sep = strpos($pRange, '!')) === false) { - return ''; - } + // Sheet title included? + if (($sep = strpos($pRange, '!')) === false) { + return ''; + } - if ($returnRange) { - return array( trim(substr($pRange, 0, $sep),"'"), - substr($pRange, $sep + 1) - ); - } + if ($returnRange) { + return array( trim(substr($pRange, 0, $sep),"'"), + substr($pRange, $sep + 1) + ); + } - return substr($pRange, $sep + 1); - } + return substr($pRange, $sep + 1); + } - /** - * Get hyperlink - * - * @param string $pCellCoordinate Cell coordinate to get hyperlink for - */ - public function getHyperlink($pCellCoordinate = 'A1') - { - // return hyperlink if we already have one - if (isset($this->_hyperlinkCollection[$pCellCoordinate])) { - return $this->_hyperlinkCollection[$pCellCoordinate]; - } + /** + * Get hyperlink + * + * @param string $pCellCoordinate Cell coordinate to get hyperlink for + */ + public function getHyperlink($pCellCoordinate = 'A1') + { + // return hyperlink if we already have one + if (isset($this->_hyperlinkCollection[$pCellCoordinate])) { + return $this->_hyperlinkCollection[$pCellCoordinate]; + } - // else create hyperlink - $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink(); - return $this->_hyperlinkCollection[$pCellCoordinate]; - } + // else create hyperlink + $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink(); + return $this->_hyperlinkCollection[$pCellCoordinate]; + } - /** - * Set hyperlnk - * - * @param string $pCellCoordinate Cell coordinate to insert hyperlink - * @param PHPExcel_Cell_Hyperlink $pHyperlink - * @return PHPExcel_Worksheet - */ - public function setHyperlink($pCellCoordinate = 'A1', PHPExcel_Cell_Hyperlink $pHyperlink = null) - { - if ($pHyperlink === null) { - unset($this->_hyperlinkCollection[$pCellCoordinate]); - } else { - $this->_hyperlinkCollection[$pCellCoordinate] = $pHyperlink; - } - return $this; - } + /** + * Set hyperlnk + * + * @param string $pCellCoordinate Cell coordinate to insert hyperlink + * @param PHPExcel_Cell_Hyperlink $pHyperlink + * @return PHPExcel_Worksheet + */ + public function setHyperlink($pCellCoordinate = 'A1', PHPExcel_Cell_Hyperlink $pHyperlink = null) + { + if ($pHyperlink === null) { + unset($this->_hyperlinkCollection[$pCellCoordinate]); + } else { + $this->_hyperlinkCollection[$pCellCoordinate] = $pHyperlink; + } + return $this; + } - /** - * Hyperlink at a specific coordinate exists? - * - * @param string $pCoordinate - * @return boolean - */ - public function hyperlinkExists($pCoordinate = 'A1') - { - return isset($this->_hyperlinkCollection[$pCoordinate]); - } + /** + * Hyperlink at a specific coordinate exists? + * + * @param string $pCoordinate + * @return boolean + */ + public function hyperlinkExists($pCoordinate = 'A1') + { + return isset($this->_hyperlinkCollection[$pCoordinate]); + } - /** - * Get collection of hyperlinks - * - * @return PHPExcel_Cell_Hyperlink[] - */ - public function getHyperlinkCollection() - { - return $this->_hyperlinkCollection; - } + /** + * Get collection of hyperlinks + * + * @return PHPExcel_Cell_Hyperlink[] + */ + public function getHyperlinkCollection() + { + return $this->_hyperlinkCollection; + } - /** - * Get data validation - * - * @param string $pCellCoordinate Cell coordinate to get data validation for - */ - public function getDataValidation($pCellCoordinate = 'A1') - { - // return data validation if we already have one - if (isset($this->_dataValidationCollection[$pCellCoordinate])) { - return $this->_dataValidationCollection[$pCellCoordinate]; - } + /** + * Get data validation + * + * @param string $pCellCoordinate Cell coordinate to get data validation for + */ + public function getDataValidation($pCellCoordinate = 'A1') + { + // return data validation if we already have one + if (isset($this->_dataValidationCollection[$pCellCoordinate])) { + return $this->_dataValidationCollection[$pCellCoordinate]; + } - // else create data validation - $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation(); - return $this->_dataValidationCollection[$pCellCoordinate]; - } + // else create data validation + $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation(); + return $this->_dataValidationCollection[$pCellCoordinate]; + } - /** - * Set data validation - * - * @param string $pCellCoordinate Cell coordinate to insert data validation - * @param PHPExcel_Cell_DataValidation $pDataValidation - * @return PHPExcel_Worksheet - */ - public function setDataValidation($pCellCoordinate = 'A1', PHPExcel_Cell_DataValidation $pDataValidation = null) - { - if ($pDataValidation === null) { - unset($this->_dataValidationCollection[$pCellCoordinate]); - } else { - $this->_dataValidationCollection[$pCellCoordinate] = $pDataValidation; - } - return $this; - } + /** + * Set data validation + * + * @param string $pCellCoordinate Cell coordinate to insert data validation + * @param PHPExcel_Cell_DataValidation $pDataValidation + * @return PHPExcel_Worksheet + */ + public function setDataValidation($pCellCoordinate = 'A1', PHPExcel_Cell_DataValidation $pDataValidation = null) + { + if ($pDataValidation === null) { + unset($this->_dataValidationCollection[$pCellCoordinate]); + } else { + $this->_dataValidationCollection[$pCellCoordinate] = $pDataValidation; + } + return $this; + } - /** - * Data validation at a specific coordinate exists? - * - * @param string $pCoordinate - * @return boolean - */ - public function dataValidationExists($pCoordinate = 'A1') - { - return isset($this->_dataValidationCollection[$pCoordinate]); - } + /** + * Data validation at a specific coordinate exists? + * + * @param string $pCoordinate + * @return boolean + */ + public function dataValidationExists($pCoordinate = 'A1') + { + return isset($this->_dataValidationCollection[$pCoordinate]); + } - /** - * Get collection of data validations - * - * @return PHPExcel_Cell_DataValidation[] - */ - public function getDataValidationCollection() - { - return $this->_dataValidationCollection; - } + /** + * Get collection of data validations + * + * @return PHPExcel_Cell_DataValidation[] + */ + public function getDataValidationCollection() + { + return $this->_dataValidationCollection; + } - /** - * Accepts a range, returning it as a range that falls within the current highest row and column of the worksheet - * - * @param string $range - * @return string Adjusted range value - */ + /** + * Accepts a range, returning it as a range that falls within the current highest row and column of the worksheet + * + * @param string $range + * @return string Adjusted range value + */ public function shrinkRangeToFit($range) { - $maxCol = $this->getHighestColumn(); - $maxRow = $this->getHighestRow(); - $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); - $rangeBlocks = explode(' ',$range); - foreach ($rangeBlocks as &$rangeSet) { - $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($rangeSet); + $rangeBlocks = explode(' ',$range); + foreach ($rangeBlocks as &$rangeSet) { + $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($rangeSet); - if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[0][0]) > $maxCol) { $rangeBoundaries[0][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } - if ($rangeBoundaries[0][1] > $maxRow) { $rangeBoundaries[0][1] = $maxRow; } - if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[1][0]) > $maxCol) { $rangeBoundaries[1][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } - if ($rangeBoundaries[1][1] > $maxRow) { $rangeBoundaries[1][1] = $maxRow; } - $rangeSet = $rangeBoundaries[0][0].$rangeBoundaries[0][1].':'.$rangeBoundaries[1][0].$rangeBoundaries[1][1]; - } - unset($rangeSet); - $stRange = implode(' ',$rangeBlocks); + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[0][0]) > $maxCol) { $rangeBoundaries[0][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[0][1] > $maxRow) { $rangeBoundaries[0][1] = $maxRow; } + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[1][0]) > $maxCol) { $rangeBoundaries[1][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[1][1] > $maxRow) { $rangeBoundaries[1][1] = $maxRow; } + $rangeSet = $rangeBoundaries[0][0].$rangeBoundaries[0][1].':'.$rangeBoundaries[1][0].$rangeBoundaries[1][1]; + } + unset($rangeSet); + $stRange = implode(' ',$rangeBlocks); - return $stRange; - } + return $stRange; + } - /** - * Get tab color - * - * @return PHPExcel_Style_Color - */ - public function getTabColor() - { - if ($this->_tabColor === NULL) - $this->_tabColor = new PHPExcel_Style_Color(); + /** + * Get tab color + * + * @return PHPExcel_Style_Color + */ + public function getTabColor() + { + if ($this->_tabColor === NULL) + $this->_tabColor = new PHPExcel_Style_Color(); - return $this->_tabColor; - } + return $this->_tabColor; + } - /** - * Reset tab color - * - * @return PHPExcel_Worksheet - */ - public function resetTabColor() - { - $this->_tabColor = null; - unset($this->_tabColor); + /** + * Reset tab color + * + * @return PHPExcel_Worksheet + */ + public function resetTabColor() + { + $this->_tabColor = null; + unset($this->_tabColor); - return $this; - } + return $this; + } - /** - * Tab color set? - * - * @return boolean - */ - public function isTabColorSet() - { - return ($this->_tabColor !== NULL); - } + /** + * Tab color set? + * + * @return boolean + */ + public function isTabColorSet() + { + return ($this->_tabColor !== NULL); + } - /** - * Copy worksheet (!= clone!) - * - * @return PHPExcel_Worksheet - */ + /** + * Copy worksheet (!= clone!) + * + * @return PHPExcel_Worksheet + */ public function copy() { - $copied = clone $this; + $copied = clone $this; - return $copied; - } + return $copied; + } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ public function __clone() { - foreach ($this as $key => $val) { - if ($key == '_parent') { - continue; - } + foreach ($this as $key => $val) { + if ($key == '_parent') { + continue; + } - if (is_object($val) || (is_array($val))) { - if ($key == '_cellCollection') { - $newCollection = clone $this->_cellCollection; - $newCollection->copyCellCollection($this); - $this->_cellCollection = $newCollection; - } elseif ($key == '_drawingCollection') { - $newCollection = clone $this->_drawingCollection; - $this->_drawingCollection = $newCollection; - } elseif (($key == '_autoFilter') && ($this->_autoFilter instanceof PHPExcel_Worksheet_AutoFilter)) { - $newAutoFilter = clone $this->_autoFilter; - $this->_autoFilter = $newAutoFilter; - $this->_autoFilter->setParent($this); - } else { - $this->{$key} = unserialize(serialize($val)); - } - } - } - } + if (is_object($val) || (is_array($val))) { + if ($key == '_cellCollection') { + $newCollection = clone $this->_cellCollection; + $newCollection->copyCellCollection($this); + $this->_cellCollection = $newCollection; + } elseif ($key == '_drawingCollection') { + $newCollection = clone $this->_drawingCollection; + $this->_drawingCollection = $newCollection; + } elseif (($key == '_autoFilter') && ($this->_autoFilter instanceof PHPExcel_Worksheet_AutoFilter)) { + $newAutoFilter = clone $this->_autoFilter; + $this->_autoFilter = $newAutoFilter; + $this->_autoFilter->setParent($this); + } else { + $this->{$key} = unserialize(serialize($val)); + } + } + } + } } diff --git a/Classes/PHPExcel/Writer/CSV.php b/Classes/PHPExcel/Writer/CSV.php index 3979d609..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($this->_phpExcel)->writeDebugLog; - PHPExcel_Calculation::getInstance($this->_phpExcel)->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($this->_phpExcel)->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 951b3397..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($this->_spreadSheet)->writeDebugLog; - PHPExcel_Calculation::getInstance($this->_spreadSheet)->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($this->_spreadSheet)->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 daa1d0fe..a63c1d1c 100644 --- a/Classes/PHPExcel/Writer/Excel5.php +++ b/Classes/PHPExcel/Writer/Excel5.php @@ -120,13 +120,13 @@ class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExce // garbage collect $this->_phpExcel->garbageCollect(); - $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->writeDebugLog; - PHPExcel_Calculation::getInstance($this->_phpExcel)->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); // initialize colors array - $this->_colors = array(); + $this->_colors = array(); // Initialise workbook writer $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, @@ -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($this->_phpExcel)->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 5aca92e9..49c7b6c3 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($this->_phpExcel)->writeDebugLog; - PHPExcel_Calculation::getInstance($this->_phpExcel)->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($this->_phpExcel)->writeDebugLog = $saveDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); } /** From 6b6f00c2af0b90baef450e920f9999a16625b5d2 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 15 Feb 2013 16:14:15 +0000 Subject: [PATCH 09/45] Changelog entry for refactored calculation engine --- changelog.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 552cb9e4..19364048 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 From be5551d29eecda8652d3827e24510a246b2d9e7b Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sat, 16 Feb 2013 10:59:19 +0000 Subject: [PATCH 10/45] Refactor the cyclic reference stack as an object so that we can inject it into the logger constructor rather than having to pass it at every call --- .../CalcEngine/CyclicReferenceStack.php | 58 +++++++++++ Classes/PHPExcel/CalcEngine/Logger.php | 34 ++++--- Classes/PHPExcel/Calculation.php | 98 ++++++++++--------- 3 files changed, 131 insertions(+), 59 deletions(-) create mode 100644 Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php 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 index 2cb893ef..250f841d 100644 --- a/Classes/PHPExcel/CalcEngine/Logger.php +++ b/Classes/PHPExcel/CalcEngine/Logger.php @@ -55,7 +55,6 @@ class PHPExcel_CalcEngine_Logger { */ private $_echoDebugLog = FALSE; - /** * The debug log generated by the calculation engine * @@ -64,6 +63,18 @@ class PHPExcel_CalcEngine_Logger { */ private $_debugLog = array(); + /** + * The calculation engine cell reference stack + * + * @var PHPExcel_CalcEngine_CyclicReferenceStack + * + */ + private $_cellStack; + + + public function __construct(PHPExcel_CalcEngine_CyclicReferenceStack $stack) { + $this->_cellStack = $stack; + } public function setWriteDebugLog($pValue = FALSE) { $this->_writeDebugLog = $pValue; @@ -81,21 +92,23 @@ class PHPExcel_CalcEngine_Logger { return $this->_echoDebugLog; } - public function writeDebugLog(array $cellReferencePath) { + public function writeDebugLog() { // Only write the debug log if logging is enabled if ($this->_writeDebugLog) { - $message = func_get_args(); - array_shift($message); - $cellReference = implode(' -> ', $cellReferencePath); - $message = implode($message); + $message = implode(func_get_args()); + $cellReference = implode(' -> ', $this->_cellStack->showStack()); if ($this->_echoDebugLog) { - echo $cellReference, (count($cellReferencePath) > 0 ? ' => ' : ''), $message,PHP_EOL; + echo $cellReference, + ($this->_cellStack->count() > 0 ? ' => ' : ''), + $message, + PHP_EOL; } - $this->_debugLog[] = $cellReference . (count($cellReferencePath) > 0 ? ' => ' : '') . $message; + $this->_debugLog[] = $cellReference . + ($this->_cellStack->count() > 0 ? ' => ' : '') . + $message; } } // function _writeDebug() - public function clearLog() { $this->_debugLog = array(); } // function flushLogger() @@ -104,6 +117,5 @@ class PHPExcel_CalcEngine_Logger { return $this->_debugLog; } // function flushLogger() - -} // class PHPExcel_Calculation_Logger +} // class PHPExcel_CalcEngine_Logger diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index e109865c..c98e50cb 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -192,7 +192,7 @@ class PHPExcel_Calculation { * @var array of string * */ - private $cyclicReferenceStack = array(); + private $_cyclicReferenceStack; private $_cyclicFormulaCount = 0; private $_cyclicFormulaCell = ''; @@ -1676,7 +1676,8 @@ class PHPExcel_Calculation { } $this->_workbook = $workbook; - $this->_debugLog = new PHPExcel_CalcEngine_Logger(); + $this->_cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack(); + $this->_debugLog = new PHPExcel_CalcEngine_Logger($this->_cyclicReferenceStack); } // function __construct() @@ -2158,7 +2159,7 @@ class PHPExcel_Calculation { // Initialise the logging settings if requested $this->formulaError = null; $this->_debugLog->clearLog(); - $this->cyclicReferenceStack = array(); + $this->_cyclicReferenceStack->clear(); $this->_cyclicFormulaCount = 1; self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; @@ -2236,7 +2237,7 @@ class PHPExcel_Calculation { // Initialise the logging settings $this->formulaError = null; $this->_debugLog->clearLog(); - $this->cyclicReferenceStack = array(); + $this->_cyclicReferenceStack->clear(); // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache @@ -2260,10 +2261,10 @@ class PHPExcel_Calculation { // Is calculation cacheing enabled? // Is the value present in calculation cache? //echo 'Test cache for ',$worksheetName,'!',$cellID,PHP_EOL; - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Testing cache value for cell ', $worksheetName, '!', $cellID); + $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($this->cyclicReferenceStack, 'Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache'); + $this->_debugLog->writeDebugLog('Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache'); // Return the cached result $cellValue = $this->_calculationCache[$worksheetName][$cellID]; return TRUE; @@ -2303,7 +2304,7 @@ class PHPExcel_Calculation { return $cellValue; } - if (($wsTitle{0} !== "\x00") && (in_array($wsTitle.'!'.$cellID,$this->cyclicReferenceStack))) { + 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) && @@ -2321,10 +2322,11 @@ class PHPExcel_Calculation { } } } - $this->cyclicReferenceStack[] = $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->cyclicReferenceStack); + $this->_cyclicReferenceStack->pop(); // Save to calculation cache if ($cellID !== NULL) { @@ -3027,9 +3029,9 @@ class PHPExcel_Calculation { // Log what we're doing if ($token == ':') { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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 @@ -3130,13 +3132,13 @@ class PHPExcel_Calculation { $matrixResult = $matrix->concat($operand2); $result = $matrixResult->getArray(); } catch (PHPExcel_Exception $ex) { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); $stack->push('Value',$result); break; case '|' : // Intersect @@ -3150,7 +3152,7 @@ class PHPExcel_Calculation { } } $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($cellIntersect)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($cellIntersect)); $stack->push('Value',$cellIntersect,$cellRef); break; } @@ -3162,11 +3164,11 @@ class PHPExcel_Calculation { $arg = $arg['value']; if ($token === '~') { // echo 'Token is a negation operator
'; - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Percentile of ', $this->_showValue($arg)); + $this->_debugLog->writeDebugLog('Evaluating Percentile of ', $this->_showValue($arg)); $multiplier = 0.01; } if (is_array($arg)) { @@ -3176,10 +3178,10 @@ class PHPExcel_Calculation { $matrixResult = $matrix1->arrayTimesEquals($multiplier); $result = $matrixResult->getArray(); } catch (PHPExcel_Exception $ex) { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'JAMA Matrix Exception: ', $ex->getMessage()); + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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); @@ -3203,23 +3205,23 @@ class PHPExcel_Calculation { } $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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, $this->_workbook->getSheetByName($matches[2]), FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Cell Range ', $cellRef, ' in current worksheet'); + $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet'); if ($pCellParent !== NULL) { $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } } } else { @@ -3236,7 +3238,7 @@ class PHPExcel_Calculation { return $this->_raiseFormulaError('Unable to access External Workbook'); } // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]); + $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { if ($this->_workbook->getSheetByName($matches[2])->cellExists($cellRef)) { $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); @@ -3247,18 +3249,18 @@ class PHPExcel_Calculation { } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Cell ', $cellRef, ' in current worksheet'); + $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; } - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } } } @@ -3271,7 +3273,7 @@ class PHPExcel_Calculation { $argCount = $stack->pop(); $argCount = $argCount['value']; if ($functionName != 'MKMATRIX') { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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])) { @@ -3316,28 +3318,28 @@ class PHPExcel_Calculation { if ($functionName != 'MKMATRIX') { if ($this->_debugLog->getWriteDebugLog()) { krsort($argArrayVals); - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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; // } // } @@ -3357,7 +3359,7 @@ class PHPExcel_Calculation { } // } if ($functionName != 'MKMATRIX') { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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)); } @@ -3368,7 +3370,7 @@ class PHPExcel_Calculation { $excelConstant = strtoupper($token); // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]); - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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); @@ -3377,10 +3379,10 @@ class PHPExcel_Calculation { // echo 'Token is a named range
'; $namedRange = $matches[6]; // echo 'Named Range is '.$namedRange.'
'; - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Named Range ', $namedRange); + $this->_debugLog->writeDebugLog('Evaluating Named Range ', $namedRange); $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellWorksheet : NULL), FALSE); $pCell->attach($pCellParent); - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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'"); @@ -3410,12 +3412,12 @@ 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->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails($operand)); + $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->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is a ', $this->_showTypeDetails('#VALUE!')); + $this->_debugLog->writeDebugLog('Evaluation Result is a ', $this->_showTypeDetails('#VALUE!')); return FALSE; } } @@ -3432,14 +3434,14 @@ class PHPExcel_Calculation { $result = array(); if ((is_array($operand1)) && (!is_array($operand2))) { foreach($operand1 as $x => $operandData) { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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']; @@ -3447,14 +3449,14 @@ class PHPExcel_Calculation { } else { if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); } foreach($operand1 as $x => $operandData) { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2[$x])); + $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->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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; @@ -3493,7 +3495,7 @@ class PHPExcel_Calculation { } // Log the result details - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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; @@ -3531,7 +3533,7 @@ class PHPExcel_Calculation { $matrixResult = $matrix->$matrixFunction($operand2); $result = $matrixResult->getArray(); } catch (PHPExcel_Exception $ex) { - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'JAMA Matrix Exception: ', $ex->getMessage()); + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } } else { @@ -3558,7 +3560,7 @@ class PHPExcel_Calculation { if ($operand2 == 0) { // Trap for Divide by Zero error $stack->push('Value','#DIV/0!'); - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, 'Evaluation Result is ', $this->_showTypeDetails('#DIV/0!')); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!')); return FALSE; } else { $result = $operand1/$operand2; @@ -3573,7 +3575,7 @@ class PHPExcel_Calculation { } // Log the result details - $this->_debugLog->writeDebugLog($this->cyclicReferenceStack, '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; @@ -3583,7 +3585,7 @@ class PHPExcel_Calculation { // trigger an error, but nicely, if need be protected function _raiseFormulaError($errorMessage) { $this->formulaError = $errorMessage; - $this->cyclicReferenceStack = array(); + $this->_cyclicReferenceStack->clear(); if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage); trigger_error($errorMessage, E_USER_ERROR); } // function _raiseFormulaError() From 9434700799f45b4b9e57766dc0c0d5bb3ec19752 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sun, 17 Feb 2013 14:57:42 +0000 Subject: [PATCH 11/45] Simplify getRed, Green and Blue methods for colour styles --- Classes/PHPExcel/Style/Color.php | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Classes/PHPExcel/Style/Color.php b/Classes/PHPExcel/Style/Color.php index ac004dba..d1aaeb0b 100644 --- a/Classes/PHPExcel/Style/Color.php +++ b/Classes/PHPExcel/Style/Color.php @@ -263,11 +263,7 @@ class PHPExcel_Style_Color extends PHPExcel_Style_Supervisor implements PHPExcel * @return string The red colour component */ public static function getRed($RGB,$hex=TRUE) { - if (strlen($RGB) == 8) { - return self::_getColourComponent($RGB, 2, $hex); - } elseif (strlen($RGB) == 6) { - return self::_getColourComponent($RGB, 0, $hex); - } + return self::_getColourComponent($RGB, strlen($RGB) - 6, $hex); } /** @@ -279,11 +275,7 @@ class PHPExcel_Style_Color extends PHPExcel_Style_Supervisor implements PHPExcel * @return string The green colour component */ public static function getGreen($RGB,$hex=TRUE) { - if (strlen($RGB) == 8) { - return self::_getColourComponent($RGB, 4, $hex); - } elseif (strlen($RGB) == 6) { - return self::_getColourComponent($RGB, 2, $hex); - } + return self::_getColourComponent($RGB, strlen($RGB) - 4, $hex); } /** @@ -295,11 +287,7 @@ class PHPExcel_Style_Color extends PHPExcel_Style_Supervisor implements PHPExcel * @return string The blue colour component */ public static function getBlue($RGB,$hex=TRUE) { - if (strlen($RGB) == 8) { - return self::_getColourComponent($RGB, 6, $hex); - } elseif (strlen($RGB) == 6) { - return self::_getColourComponent($RGB, 4, $hex); - } + return self::_getColourComponent($RGB, strlen($RGB) - 2, $hex); } /** From 3ea55ce28757f427dbc7cbe45660c16ccb77ce62 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Tue, 19 Feb 2013 12:23:38 +0000 Subject: [PATCH 12/45] Fix for composite charts indexing and ordering for each group Added example for generating a composite chart --- Classes/PHPExcel/Writer/Excel2007/Chart.php | 7 +- Examples/33chartcreate-composite-chart.php | 205 ++++++++++++++++++++ Examples/runall.php | 2 + 3 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 Examples/33chartcreate-composite-chart.php diff --git a/Classes/PHPExcel/Writer/Excel2007/Chart.php b/Classes/PHPExcel/Writer/Excel2007/Chart.php index 1a727384..9ef40f5d 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Chart.php +++ b/Classes/PHPExcel/Writer/Excel2007/Chart.php @@ -230,6 +230,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa } $id1 = $id2 = 0; + $this->_seriesIndex = 0; $objWriter->startElement('c:plotArea'); $layout = $plotArea->getLayout(); @@ -737,11 +738,11 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('c:ser'); $objWriter->startElement('c:idx'); - $objWriter->writeAttribute('val', $plotSeriesIdx); + $objWriter->writeAttribute('val', $this->_seriesIndex + $plotSeriesIdx); $objWriter->endElement(); $objWriter->startElement('c:order'); - $objWriter->writeAttribute('val', $plotSeriesRef); + $objWriter->writeAttribute('val', $this->_seriesIndex + $plotSeriesRef); $objWriter->endElement(); if (($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART) || @@ -865,6 +866,8 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->endElement(); } + + $this->_seriesIndex += $plotSeriesIdx + 1; } /** diff --git a/Examples/33chartcreate-composite-chart.php b/Examples/33chartcreate-composite-chart.php new file mode 100644 index 00000000..14496f1c --- /dev/null +++ b/Examples/33chartcreate-composite-chart.php @@ -0,0 +1,205 @@ +'); + +date_default_timezone_set('Europe/London'); + +/** + * PHPExcel + * + * Copyright (C) 2006 - 2012 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version ##VERSION##, ##DATE## + */ + +/** Include path **/ +set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); + +/** PHPExcel */ +include 'PHPExcel.php'; + +$objPHPExcel = new PHPExcel(); +$objWorksheet = $objPHPExcel->getActiveSheet(); +$objWorksheet->fromArray( + array( + array('', 'Rainfall (mm)', 'Temperature (°F)', 'Humidity (%)'), + array('Jan', 78, 52, 61), + array('Feb', 64, 54, 62), + array('Mar', 62, 57, 63), + array('Apr', 21, 62, 59), + array('May', 11, 75, 60), + array('Jun', 1, 75, 57), + array('Jul', 1, 79, 56), + array('Aug', 1, 79, 59), + array('Sep', 10, 75, 60), + array('Oct', 40, 68, 63), + array('Nov', 69, 62, 64), + array('Dec', 89, 57, 66), + ) +); + + +// Set the Labels for each data series we want to plot +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$dataseriesLabels1 = array( + new PHPExcel_Chart_DataSeriesValues('String', 'Worksheet!$B$1', NULL, 1), // Temperature +); +$dataseriesLabels2 = array( + new PHPExcel_Chart_DataSeriesValues('String', 'Worksheet!$C$1', NULL, 1), // Rainfall +); +$dataseriesLabels3 = array( + new PHPExcel_Chart_DataSeriesValues('String', 'Worksheet!$D$1', NULL, 1), // Humidity +); + +// Set the X-Axis Labels +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$xAxisTickValues = array( + new PHPExcel_Chart_DataSeriesValues('String', 'Worksheet!$A$2:$A$13', NULL, 12), // Jan to Dec +); + + +// Set the Data values for each data series we want to plot +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$dataSeriesValues1 = array( + new PHPExcel_Chart_DataSeriesValues('Number', 'Worksheet!$B$2:$B$13', NULL, 12), +); + +// Build the dataseries +$series1 = new PHPExcel_Chart_DataSeries( + PHPExcel_Chart_DataSeries::TYPE_BARCHART, // plotType + PHPExcel_Chart_DataSeries::GROUPING_CLUSTERED, // plotGrouping + range(0, count($dataSeriesValues1)-1), // plotOrder + $dataseriesLabels1, // plotLabel + $xAxisTickValues, // plotCategory + $dataSeriesValues1 // plotValues +); +// Set additional dataseries parameters +// Make it a vertical column rather than a horizontal bar graph +$series1->setPlotDirection(PHPExcel_Chart_DataSeries::DIRECTION_COL); + + +// Set the Data values for each data series we want to plot +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$dataSeriesValues2 = array( + new PHPExcel_Chart_DataSeriesValues('Number', 'Worksheet!$C$2:$C$13', NULL, 12), +); + +// Build the dataseries +$series2 = new PHPExcel_Chart_DataSeries( + PHPExcel_Chart_DataSeries::TYPE_LINECHART, // plotType + PHPExcel_Chart_DataSeries::GROUPING_STANDARD, // plotGrouping + range(0, count($dataSeriesValues2)-1), // plotOrder + $dataseriesLabels2, // plotLabel + NULL, // plotCategory + $dataSeriesValues2 // plotValues +); + + +// Set the Data values for each data series we want to plot +// Datatype +// Cell reference for data +// Format Code +// Number of datapoints in series +// Data values +// Data Marker +$dataSeriesValues3 = array( + new PHPExcel_Chart_DataSeriesValues('Number', 'Worksheet!$D$2:$D$13', NULL, 12), +); + +// Build the dataseries +$series3 = new PHPExcel_Chart_DataSeries( + PHPExcel_Chart_DataSeries::TYPE_AREACHART, // plotType + PHPExcel_Chart_DataSeries::GROUPING_STANDARD, // plotGrouping + range(0, count($dataSeriesValues2)-1), // plotOrder + $dataseriesLabels3, // plotLabel + NULL, // plotCategory + $dataSeriesValues3 // plotValues +); + + +// Set the series in the plot area +$plotarea = new PHPExcel_Chart_PlotArea(NULL, array($series1, $series2, $series3)); +// Set the chart legend +$legend = new PHPExcel_Chart_Legend(PHPExcel_Chart_Legend::POSITION_RIGHT, NULL, false); + +$title = new PHPExcel_Chart_Title('Average Weather Chart for Crete'); + + +// Create the chart +$chart = new PHPExcel_Chart( + 'chart1', // name + $title, // title + $legend, // legend + $plotarea, // plotArea + true, // plotVisibleOnly + 0, // displayBlanksAs + NULL, // xAxisLabel + NULL // yAxisLabel +); + +// Set the position where the chart should appear in the worksheet +$chart->setTopLeftPosition('F2'); +$chart->setBottomRightPosition('O16'); + +// Add the chart to the worksheet +$objWorksheet->addChart($chart); + + +// Save Excel 2007 file +echo date('H:i:s') , " Write to Excel2007 format" , EOL; +$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); +$objWriter->setIncludeCharts(TRUE); +$objWriter->save(str_replace('.php', '.xlsx', __FILE__)); +echo date('H:i:s') , " File written to " , str_replace('.php', '.xlsx', pathinfo(__FILE__, PATHINFO_BASENAME)) , 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/runall.php b/Examples/runall.php index 3dfaa1f6..ad37f339 100644 --- a/Examples/runall.php +++ b/Examples/runall.php @@ -82,6 +82,8 @@ $aTests = array( , '33chartcreate-line.php' , '33chartcreate-pie.php' , '33chartcreate-radar.php' + , '33chartcreate-multiple-charts.php' + , '33chartcreate-composite.php' , '34chartupdate.php' , '35chartrender.php' , '36chartreadwriteHTML.php' From db75c5981aaf78c0a6193e2019e86df778a272d8 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Thu, 21 Feb 2013 11:29:32 +0000 Subject: [PATCH 13/45] Fixes to Advanced Value Binder for cell restructuring --- Classes/PHPExcel/Cell.php | 3 ++- Classes/PHPExcel/Cell/AdvancedValueBinder.php | 18 +++++++++--------- .../PHPExcel/Cell/AdvancedValueBinderTest.php | 16 ++++++++++++++-- .../PHPExcel/Worksheet/AutoFilterTest.php | 6 ++++++ .../Calculation/DateTime/DATEVALUE.data | 8 ++++---- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php index e21674aa..1b944bbc 100644 --- a/Classes/PHPExcel/Cell.php +++ b/Classes/PHPExcel/Cell.php @@ -104,6 +104,7 @@ class PHPExcel_Cell **/ public function notifyCacheController() { $this->_parent->updateCacheData($this); + return $this; } @@ -133,7 +134,7 @@ class PHPExcel_Cell // Set worksheet cache $this->_parent = $pSheet->getCellCacheController(); - + // Set datatype? if ($pDataType !== NULL) { if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2) 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/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!" From d42361e8bf31acc5fc1b74f1dcbb5c7b20e42a94 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Thu, 21 Feb 2013 11:44:33 +0000 Subject: [PATCH 14/45] Correct attachment of cells to cache collection as parent rather than worksheet --- Classes/PHPExcel/CachedObjectStorage/APC.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/CacheBase.php | 2 +- Classes/PHPExcel/CachedObjectStorage/DiscISAM.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/Igbinary.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/Memcache.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/PHPTemp.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/SQLite.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/SQLite3.php | 4 ++-- Classes/PHPExcel/CachedObjectStorage/Wincache.php | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) 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 0651b4a3..2176c0ca 100644 --- a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php +++ b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php @@ -259,7 +259,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/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..0bafbb72 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; diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php index f9ca246e..37615d0a 100644 --- a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php +++ b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php @@ -119,8 +119,8 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ $this->_currentObjectID = $pCoord; $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; 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; From 6ae1a501c5cf0a821f155c382118340e3a6e2c35 Mon Sep 17 00:00:00 2001 From: Matthias Laug Date: Thu, 21 Feb 2013 14:35:59 +0100 Subject: [PATCH 15/45] Fatal Error on non object in Worksheet.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the disconnectCells method is not always fully initialized with the attribute  _cellCollection, so a check needs to be done. Otherwise a fatal error occurs. happens if multiple xsl are created from csv file --- Classes/PHPExcel/Worksheet.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index c8b70fe1..c9830fc0 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -378,9 +378,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function disconnectCells() { - $this->_cellCollection->unsetWorksheetCells(); - $this->_cellCollection = NULL; - + if ( $this->_cellCollection != null ){ + $this->_cellCollection->unsetWorksheetCells(); + $this->_cellCollection = NULL; + } // detach ourself from the workbook, so that it can then delete this worksheet successfully $this->_parent = null; } From 7b922bbf77c7d4d9e5c39ea1ee2e3de502e10d6c Mon Sep 17 00:00:00 2001 From: Dominik Bonsch Date: Thu, 21 Feb 2013 19:34:41 +0100 Subject: [PATCH 16/45] changed NULL to null --- Classes/PHPExcel/Worksheet.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index c9830fc0..738d1674 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); } @@ -380,7 +380,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable { 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,7 +391,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * */ function __destruct() { - if ($this->_cellCollection !== NULL) { + if ($this->_cellCollection !== null) { $this->disconnectCells(); } } @@ -451,7 +451,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 +464,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function sortCellCollection() { - if ($this->_cellCollection !== NULL) { + if ($this->_cellCollection !== null) { return $this->_cellCollection->getSortedCellList(); } return array(); @@ -1117,7 +1117,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable 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 +1136,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($pCoordinate, null, PHPExcel_Cell_DataType::TYPE_NULL, $this)); $this->_cellCollectionIsSorted = false; if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) @@ -1176,7 +1176,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($coordinate, null, PHPExcel_Cell_DataType::TYPE_NULL, $this)); $this->_cellCollectionIsSorted = false; if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) @@ -1209,7 +1209,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable 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()) { @@ -1899,7 +1899,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function removeAutoFilter() { - $this->_autoFilter->setRange(NULL); + $this->_autoFilter->setRange(null); return $this; } @@ -2442,7 +2442,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable ); } } else { - // Cell holds a NULL + // Cell holds a null $returnValue[$rRef][$cRef] = $nullValue; } } else { @@ -2475,7 +2475,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable ) { $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); - if ($namedRange !== NULL) { + if ($namedRange !== null) { $pWorkSheet = $namedRange->getWorksheet(); $pCellRange = $namedRange->getRange(); @@ -2759,7 +2759,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; @@ -2785,7 +2785,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function isTabColorSet() { - return ($this->_tabColor !== NULL); + return ($this->_tabColor !== null); } /** From e47b543c895ce7f45ce4a8d424835bec6157bce9 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 27 Feb 2013 12:18:34 +0000 Subject: [PATCH 17/45] Bugfix: Work item GH-80 - "Sheet index is out of bounds." Exception --- Classes/PHPExcel/Reader/Excel2007.php | 19 ++++++++++--------- changelog.txt | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Classes/PHPExcel/Reader/Excel2007.php b/Classes/PHPExcel/Reader/Excel2007.php index bd91592d..e2a677de 100644 --- a/Classes/PHPExcel/Reader/Excel2007.php +++ b/Classes/PHPExcel/Reader/Excel2007.php @@ -1608,15 +1608,16 @@ class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPE break; default: - $range = explode('!', (string)$definedName); - if (count($range) == 2) { - $range[0] = str_replace("''", "'", $range[0]); - $range[0] = str_replace("'", "", $range[0]); - if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { - $extractedRange = str_replace('$', '', $range[1]); - $scope = $docSheet->getParent()->getSheet((string)$definedName['localSheetId']); - - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) { + $range = explode('!', (string)$definedName); + if (count($range) == 2) { + $range[0] = str_replace("''", "'", $range[0]); + $range[0] = str_replace("'", "", $range[0]); + if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]); + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + } } } break; diff --git a/changelog.txt b/changelog.txt index 552cb9e4..e02c3a4a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -50,7 +50,7 @@ Fixed in develop branch: - Bugfix: (MBaker) Work item GH-104 - echo statements in HTML.php - Feature: (Progi1984) Work item GH-8/CP11704 : Conditional formatting in Excel 5 Writer - 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 -------------------------------------------------------------------------------- BREAKING CHANGE! As part of the planned changes for handling array formulae in From a49b3c48341f30bd5630cd79a8f38ee71875fadc Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 27 Feb 2013 12:52:57 +0000 Subject: [PATCH 18/45] Example of cell-level protection in a worksheet --- Examples/12cellProtection.php | 107 ++++++++++++++++++++++++++++++++++ Examples/runall.php | 1 + 2 files changed, 108 insertions(+) create mode 100644 Examples/12cellProtection.php diff --git a/Examples/12cellProtection.php b/Examples/12cellProtection.php new file mode 100644 index 00000000..caa38767 --- /dev/null +++ b/Examples/12cellProtection.php @@ -0,0 +1,107 @@ +'); + +date_default_timezone_set('Europe/London'); + +/** Include PHPExcel */ +require_once '../Classes/PHPExcel.php'; + + +// 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 document properties" , EOL; +$objPHPExcel->getProperties()->setCreator("Mark Baker") + ->setLastModifiedBy("Mark Baker") + ->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"); + + +// Add some data +echo date('H:i:s') , " Add some data" , EOL; +$objPHPExcel->setActiveSheetIndex(0); +$objPHPExcel->getActiveSheet()->setCellValue('A1', 'Crouching'); +$objPHPExcel->getActiveSheet()->setCellValue('B1', 'Tiger'); +$objPHPExcel->getActiveSheet()->setCellValue('A2', 'Hidden'); +$objPHPExcel->getActiveSheet()->setCellValue('B2', 'Dragon'); + +// Rename worksheet +echo date('H:i:s') , " Rename worksheet" , EOL; +$objPHPExcel->getActiveSheet()->setTitle('Simple'); + + +// Set document security +echo date('H:i:s') , " Set cell protection" , EOL; + + +// Set sheet security +echo date('H:i:s') , " Set sheet security" , EOL; +$objPHPExcel->getActiveSheet()->getProtection()->setSheet(true); +$objPHPExcel->getActiveSheet() + ->getStyle('A2:B2') + ->getProtection()->setLocked( + PHPExcel_Style_Protection::PROTECTION_UNPROTECTED + ); + + +// 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/runall.php b/Examples/runall.php index ad37f339..7e97ee82 100644 --- a/Examples/runall.php +++ b/Examples/runall.php @@ -52,6 +52,7 @@ $aTests = array( , '10autofilter-selection-2.php' , '11documentsecurity.php' , '11documentsecurity-xls.php' + , '12cellProtection.php' , '13calculation.php' , '14excel5.php' , '15datavalidation.php' From 429ad592843d3aa415608cb17d1a7f5116152852 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 27 Feb 2013 17:54:45 +0000 Subject: [PATCH 19/45] Method for moving cells in the cell cache without needing to access the cell itself TODO Sqlite cell cache needs equivalent method for updating cache database rather than simply the indexed cache array --- .../CachedObjectStorage/CacheBase.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php index 0651b4a3..b6cf4be0 100644 --- a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php +++ b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php @@ -106,6 +106,26 @@ 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; + } + if (isset($this->_cellCache[$fromAddress])) { + $this->_cellCache[$toAddress] = &$this->_cellCache[$fromAddress]; + unset($this->_cellCache[$fromAddress]); + } + + return TRUE; + } // function isDataSet() + + /** * Add or Update a cell in cache * From ae9d9fd75864028e9a89599def7dc9338639271e Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 27 Feb 2013 23:13:49 +0000 Subject: [PATCH 20/45] Add move cell method for SQLite. TODO - modify SQLite3 to use parameterised statements consistently throughout --- .../CachedObjectStorage/CacheBase.php | 3 ++- .../PHPExcel/CachedObjectStorage/SQLite.php | 26 +++++++++++++++++++ .../PHPExcel/CachedObjectStorage/SQLite3.php | 26 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php index e5fc678c..6dd6c1a5 100644 --- a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php +++ b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php @@ -117,13 +117,14 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { 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 isDataSet() + } // function moveCell() /** diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite.php b/Classes/PHPExcel/CachedObjectStorage/SQLite.php index 0bafbb72..d717c499 100644 --- a/Classes/PHPExcel/CachedObjectStorage/SQLite.php +++ b/Classes/PHPExcel/CachedObjectStorage/SQLite.php @@ -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 * diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php index 37615d0a..5886c3c3 100644 --- a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php +++ b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php @@ -173,6 +173,32 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ } // 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 * From e5613be860f590e8fd1ff17e060cd99d05fe1a27 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Thu, 28 Feb 2013 12:22:10 +0000 Subject: [PATCH 21/45] Ensure that values returned get getCalculatedValue aren't array values, irrespective of the returnArrayAsType setting --- Classes/PHPExcel/Cell.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php index 1b944bbc..cbaddc15 100644 --- a/Classes/PHPExcel/Cell.php +++ b/Classes/PHPExcel/Cell.php @@ -134,7 +134,7 @@ class PHPExcel_Cell // Set worksheet cache $this->_parent = $pSheet->getCellCacheController(); - + // Set datatype? if ($pDataType !== NULL) { if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2) @@ -273,21 +273,26 @@ 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
'; +//echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value'.PHP_EOL; $result = PHPExcel_Calculation::getInstance( $this->getWorksheet()->getParent() )->calculateCellValue($this,$resetLog); -// $result = $this->getParent()->getParent()->getCalculationEngine()->calculateCellValue($this,$resetLog); -// echo $this->getCoordinate().' calculation result is '.$result.'
'; +//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( @@ -297,10 +302,10 @@ class PHPExcel_Cell } 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; } From 5144932a8b956901fc5c4c4fe7b12d08d1b24ffa Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 1 Mar 2013 13:50:06 +0000 Subject: [PATCH 22/45] Make consistent use of prepared statements --- .../PHPExcel/CachedObjectStorage/SQLite3.php | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php index 5886c3c3..c3a1deb5 100644 --- a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php +++ b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php @@ -106,19 +106,22 @@ 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) { + $query = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id"); + $query->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $query->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); + $this->_currentObject = unserialize($cellData['value']); // Re-attach this as the cell's parent $this->_currentObject->attach($this); @@ -135,19 +138,19 @@ 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) { + $query = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id"); + $query->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $query->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,16 +163,17 @@ 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); - if ($result === false) + $query = $this->_DBHandle->prepare("DELETE FROM kvp_".$this->_TableName." WHERE id = :id"); + $query->bindValue('id',$pCoord,SQLITE3_TEXT); + $result = $query->execute(); + if ($result === FALSE) throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); - $this->_currentCellIsDirty = false; + $this->_currentCellIsDirty = FALSE; } // function deleteCacheData() From 6145cf326b7492c2297430f5acdf71c5712027d1 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 1 Mar 2013 21:38:13 +0000 Subject: [PATCH 23/45] Bugfix: (ccorliss) Work item GH-105 - Fixed number format fatal error --- Classes/PHPExcel/Style/NumberFormat.php | 2 +- Classes/PHPExcel/Worksheet.php | 5 ++++- changelog.txt | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Classes/PHPExcel/Style/NumberFormat.php b/Classes/PHPExcel/Style/NumberFormat.php index ed6ace90..dde1ad99 100644 --- a/Classes/PHPExcel/Style/NumberFormat.php +++ b/Classes/PHPExcel/Style/NumberFormat.php @@ -439,7 +439,7 @@ class PHPExcel_Style_NumberFormat extends PHPExcel_Style_Supervisor implements P * @param array $callBack Callback function for additional formatting of string * @return string Formatted string */ - public static function toFormattedString($value = '', $format = '', $callBack = null) + public static function toFormattedString($value = PHPExcel_Style_NumberFormat::FORMAT_GENERAL, $format = '', $callBack = null) { // For now we do not treat strings although section 4 of a format code affects strings if (!is_numeric($value)) return $value; diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index 738d1674..5357a938 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -2438,7 +2438,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ($formatData) { $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( - $returnValue[$rRef][$cRef], $style->getNumberFormat()->getFormatCode() + $returnValue[$rRef][$cRef], + ($style->getNumberFormat()) ? + $style->getNumberFormat()->getFormatCode() : + PHPExcel_Style_NumberFormat::FORMAT_GENERAL ); } } else { diff --git a/changelog.txt b/changelog.txt index e02c3a4a..600a33fd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -51,6 +51,7 @@ Fixed in develop branch: - Feature: (Progi1984) Work item GH-8/CP11704 : Conditional formatting in Excel 5 Writer - 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 -------------------------------------------------------------------------------- BREAKING CHANGE! As part of the planned changes for handling array formulae in From 8a97503f175d1d68b443ce96847cecbcea22ae65 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 6 Mar 2013 17:19:22 +0000 Subject: [PATCH 24/45] Bugfix: Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers --- .../PHPExcel/CachedObjectStorage/SQLite.php | 4 + .../PHPExcel/CachedObjectStorage/SQLite3.php | 1 + .../06largescale-with-cellcaching-sqlite.php | 126 ++++++++++++++++++ .../06largescale-with-cellcaching-sqlite3.php | 126 ++++++++++++++++++ changelog.txt | 1 + 5 files changed, 258 insertions(+) create mode 100644 Examples/06largescale-with-cellcaching-sqlite.php create mode 100644 Examples/06largescale-with-cellcaching-sqlite3.php diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite.php b/Classes/PHPExcel/CachedObjectStorage/SQLite.php index d717c499..5e82c089 100644 --- a/Classes/PHPExcel/CachedObjectStorage/SQLite.php +++ b/Classes/PHPExcel/CachedObjectStorage/SQLite.php @@ -282,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 c3a1deb5..35fd73ee 100644 --- a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php +++ b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php @@ -291,6 +291,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/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 b626123b..27410f85 100644 --- a/changelog.txt +++ b/changelog.txt @@ -54,6 +54,7 @@ Fixed in develop branch for release v1.7.9: - 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 From 5940e40362eeacf7ac66ef9238826973db531c84 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 6 Mar 2013 17:43:12 +0000 Subject: [PATCH 25/45] Make prepared statements re-usable --- .../PHPExcel/CachedObjectStorage/SQLite3.php | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Classes/PHPExcel/CachedObjectStorage/SQLite3.php b/Classes/PHPExcel/CachedObjectStorage/SQLite3.php index 35fd73ee..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,9 +110,8 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ } $this->_storeData(); - $query = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id"); - $query->bindValue('id',$pCoord,SQLITE3_TEXT); - $cellResult = $query->execute(); + $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $this->_selectQuery->execute(); if ($cellResult === FALSE) { throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); } @@ -142,9 +145,8 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ } // Check if the requested entry exists in the cache - $query = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id"); - $query->bindValue('id',$pCoord,SQLITE3_TEXT); - $cellResult = $query->execute(); + $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $this->_selectQuery->execute(); if ($cellResult === FALSE) { throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); } @@ -167,9 +169,8 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ } // Check if the requested entry exists in the cache - $query = $this->_DBHandle->prepare("DELETE FROM kvp_".$this->_TableName." WHERE id = :id"); - $query->bindValue('id',$pCoord,SQLITE3_TEXT); - $result = $query->execute(); + $this->_deleteQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $result = $this->_deleteQuery->execute(); if ($result === FALSE) throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); @@ -189,13 +190,14 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ $this->_currentObjectID = $toAddress; } - $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$toAddress."'"; - $result = $this->_DBHandle->exec($query); + $this->_deleteQuery->bindValue('id',$toAddress,SQLITE3_TEXT); + $result = $this->_deleteQuery->execute(); 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); + $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()); @@ -283,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() From fb16712e13f4240403859771c87647f8ce1f8ba3 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 6 Mar 2013 21:38:42 +0000 Subject: [PATCH 26/45] Some work on page margins for HTML Writer, and initial elements for DomPDF PDF Writer --- Classes/PHPExcel/Writer/HTML.php | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index d07dbd2d..fb467f36 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -1016,7 +1016,8 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ // Construct HTML $html = ''; - + $html .= $this->_setMargins($pSheet); + if (!$this->_useInlineCss) { $gridlines = $pSheet->getShowGridLines() ? ' gridlines' : ''; $html .= ' ' . PHP_EOL; @@ -1495,4 +1496,27 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ $this->_spansAreCalculated = true; } + private function _setMargins(PHPExcel_Worksheet $pSheet) { + $htmlPage = '@page { '; + $htmlBody = 'body { '; + + $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; '; + $htmlPage .= 'left-margin: ' . $left; + $htmlBody .= 'left-margin: ' . $left; + $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; '; + $htmlPage .= 'right-margin: ' . $right; + $htmlBody .= 'right-margin: ' . $right; + $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; '; + $htmlPage .= 'top-margin: ' . $top; + $htmlBody .= 'top-margin: ' . $top; + $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; '; + $htmlPage .= 'bottom-margin: ' . $bottom; + $htmlBody .= 'bottom-margin: ' . $bottom; + + $htmlPage .= "}\n"; + $htmlBody .= "}\n"; + + return "\n"; + } + } From 316f86e03c02b9112bd7c54de83b5738defd869f Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sun, 10 Mar 2013 23:15:57 +0000 Subject: [PATCH 27/45] Docblock comments --- Classes/PHPExcel/Calculation/Engineering.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/PHPExcel/Calculation/Engineering.php b/Classes/PHPExcel/Calculation/Engineering.php index 84dcd388..c0005e74 100644 --- a/Classes/PHPExcel/Calculation/Engineering.php +++ b/Classes/PHPExcel/Calculation/Engineering.php @@ -1932,7 +1932,7 @@ class PHPExcel_Calculation_Engineering { /** * IMLOG2 * - * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format. + * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format. * * Excel Function: * IMLOG2(complexNumber) From 80e3c46f3a5d28625a610c93a16ceb8239727da4 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sat, 16 Mar 2013 00:18:38 +0000 Subject: [PATCH 28/45] iconv() is more efficient than mb_convert_encoding() --- Classes/PHPExcel/Shared/String.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Classes/PHPExcel/Shared/String.php b/Classes/PHPExcel/Shared/String.php index 3e495e82..31e2ef34 100644 --- a/Classes/PHPExcel/Shared/String.php +++ b/Classes/PHPExcel/Shared/String.php @@ -482,7 +482,7 @@ class PHPExcel_Shared_String } /** - * Convert string from one encoding to another. First try iconv, then mbstring, or no convertion + * Convert string from one encoding to another. First try mbstring, then iconv, finally strlen * * @param string $value * @param string $to Encoding to convert to, e.g. 'UTF-8' @@ -491,14 +491,14 @@ class PHPExcel_Shared_String */ public static function ConvertEncoding($value, $to, $from) { - if (self::getIsIconvEnabled()) { - return iconv($from, $to, $value); - } - if (self::getIsMbstringEnabled()) { return mb_convert_encoding($value, $to, $from); } + if (self::getIsIconvEnabled()) { + return iconv($from, $to, $value); + } + if($from == 'UTF-16LE'){ return self::utf16_decode($value, false); }else if($from == 'UTF-16BE'){ @@ -548,20 +548,20 @@ class PHPExcel_Shared_String */ public static function CountCharacters($value, $enc = 'UTF-8') { - if (self::getIsIconvEnabled()) { - return iconv_strlen($value, $enc); - } - if (self::getIsMbstringEnabled()) { return mb_strlen($value, $enc); } + if (self::getIsIconvEnabled()) { + return iconv_strlen($value, $enc); + } + // else strlen return strlen($value); } /** - * Get a substring of a UTF-8 encoded string + * Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen * * @param string $pValue UTF-8 encoded string * @param int $start Start offset @@ -570,14 +570,14 @@ class PHPExcel_Shared_String */ public static function Substring($pValue = '', $pStart = 0, $pLength = 0) { - if (self::getIsIconvEnabled()) { - return iconv_substr($pValue, $pStart, $pLength, 'UTF-8'); - } - if (self::getIsMbstringEnabled()) { return mb_substr($pValue, $pStart, $pLength, 'UTF-8'); } + if (self::getIsIconvEnabled()) { + return iconv_substr($pValue, $pStart, $pLength, 'UTF-8'); + } + // else substr return substr($pValue, $pStart, $pLength); } From b42d4a353cc98709a9ef463ec7a3dee0aa0ffa34 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Wed, 20 Mar 2013 13:48:25 +0000 Subject: [PATCH 29/45] Fix reference to worksheet/cell collection from cell in isDateTime() --- Classes/PHPExcel/Shared/Date.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/PHPExcel/Shared/Date.php b/Classes/PHPExcel/Shared/Date.php index d74e9674..68076ce1 100644 --- a/Classes/PHPExcel/Shared/Date.php +++ b/Classes/PHPExcel/Shared/Date.php @@ -253,7 +253,7 @@ class PHPExcel_Shared_Date */ public static function isDateTime(PHPExcel_Cell $pCell) { return self::isDateTimeFormat( - $pCell->getParent()->getStyle( + $pCell->getWorksheet()->getStyle( $pCell->getCoordinate() )->getNumberFormat() ); From 477902570160a5c1a070bf157ce146a373076f2d Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 22 Mar 2013 14:09:22 +0000 Subject: [PATCH 30/45] General: Work item GH-98 - Split repository in order to improve distribution of the library via composer Added .gitattributes file to identify files/folders that should be excluded from a composer distribution unless invoked as composer install --prefer-source --- .gitattributes | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1bc28be4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +/Build export-ignore +/Documentation export-ignore +/Tests export-ignore +README.md export-ignore From d79bdc5b19ba10326ad92876b0eb65ead5b5d6da Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sun, 24 Mar 2013 21:56:06 +0000 Subject: [PATCH 31/45] iconv rather than mbstring for convert encoding --- Classes/PHPExcel/Shared/String.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Classes/PHPExcel/Shared/String.php b/Classes/PHPExcel/Shared/String.php index 31e2ef34..38974336 100644 --- a/Classes/PHPExcel/Shared/String.php +++ b/Classes/PHPExcel/Shared/String.php @@ -491,14 +491,14 @@ class PHPExcel_Shared_String */ public static function ConvertEncoding($value, $to, $from) { - if (self::getIsMbstringEnabled()) { - return mb_convert_encoding($value, $to, $from); - } - if (self::getIsIconvEnabled()) { return iconv($from, $to, $value); } + if (self::getIsMbstringEnabled()) { + return mb_convert_encoding($value, $to, $from); + } + if($from == 'UTF-16LE'){ return self::utf16_decode($value, false); }else if($from == 'UTF-16BE'){ From 0c15e8abb71a358d8622ae2eedcdbbb2da1346bf Mon Sep 17 00:00:00 2001 From: Phill Sparks Date: Wed, 27 Mar 2013 16:12:35 +0000 Subject: [PATCH 32/45] Fix Excel5 category Update Excel5.php to remove hard-coded "Test result file" category --- Classes/PHPExcel/Writer/Excel5.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Classes/PHPExcel/Writer/Excel5.php b/Classes/PHPExcel/Writer/Excel5.php index a63c1d1c..37f5b85c 100644 --- a/Classes/PHPExcel/Writer/Excel5.php +++ b/Classes/PHPExcel/Writer/Excel5.php @@ -596,7 +596,6 @@ class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExce // GKPIDDSI_CATEGORY : Category if($this->_phpExcel->getProperties()->getCategory()){ $dataProp = $this->_phpExcel->getProperties()->getCategory(); - $dataProp = 'Test result file'; $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), 'offset' => array('pack' => 'V'), 'type' => array('pack' => 'V', 'data' => 0x1E), @@ -933,4 +932,4 @@ class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExce return $data; } -} \ No newline at end of file +} From 663b8a190342a86a67501caa37067350372b4021 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 29 Mar 2013 11:15:36 +0000 Subject: [PATCH 33/45] General: Modify cell's getCalculatedValue() method to return the content of RichText objects rather than the RichText object itself --- Classes/PHPExcel/Cell.php | 8 +++----- changelog.txt | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php index cbaddc15..dbd7a822 100644 --- a/Classes/PHPExcel/Cell.php +++ b/Classes/PHPExcel/Cell.php @@ -307,12 +307,10 @@ class PHPExcel_Cell } //echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().PHP_EOL; return $result; + } elseif($this->_value instanceof PHPExcel_RichText) { +// echo 'Cell value for '.$this->getCoordinate().' is rich text: Returning data value of '.$this->_value.'
'; + return $this->_value->getPlainText(); } - -// if ($this->_value === NULL) { -// echo 'Cell '.$this->getCoordinate().' has no value, formula or otherwise
'; -// return NULL; -// } // echo 'Cell value for '.$this->getCoordinate().' is not a formula: Returning data value of '.$this->_value.'
'; return $this->_value; } diff --git a/changelog.txt b/changelog.txt index 27410f85..afdadb0d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -43,6 +43,7 @@ Fixed in develop branch for release v1.7.9: - 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 +- General: (MBaker) Modify cell's getCalculatedValue() method to return the content of RichText objects rather than the RichText object itself - 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 From db7b99ac8ee04e52c4e4bf35df4714dcb3f50321 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 1 Apr 2013 17:26:26 +0100 Subject: [PATCH 34/45] Bugfix: (alexgann) Work item GH-154 - Fix merged-cell borders on HTML/PDF output --- Classes/PHPExcel/Writer/HTML.php | 10 +++++++++- changelog.txt | 8 +++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index a30033f1..f50412e5 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -966,7 +966,10 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ */ private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) { // Create CSS - $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); +// $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); + // Create CSS - add !important to non-none border styles for merged cells + $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle()); + $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); // Return return $css; @@ -1229,6 +1232,11 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; $rowSpan = $spans['rowspan']; $colSpan = $spans['colspan']; + + // Also apply style from last cell in merge to fix borders - + // relies on !important for non-none border declarations in _createCSSStyleBorder + $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan); + $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex(); } // Write diff --git a/changelog.txt b/changelog.txt index afdadb0d..16a7ac10 100644 --- a/changelog.txt +++ b/changelog.txt @@ -56,13 +56,15 @@ Fixed in develop branch for release v1.7.9: - 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 +- Bugfix: (alexgann) Work item GH-154 - Fix merged-cell borders on HTML/PDF output + -------------------------------------------------------------------------------- BREAKING CHANGE! As part of the planned changes for handling array formulae in workbooks, there are some changes that will affect the PHPExcel_Cell object methods. -The following methods are now deprecated, and will be removed in version 1.7.9: +The following methods are now deprecated, and will be removed in or after version 1.8.0: getCalculatedValue() The getValue() method will return calculated values for cells containing formulae instead. setCalculatedValue() The cell value will always contain the result of a @@ -72,7 +74,7 @@ The following methods are now deprecated, and will be removed in version 1.7.9: getFormulaAttributes() This will be replaced by the getArrayFormulaRange() method. -The following methods will be added in version 1.7.9 +The following methods will be added in version 1.8.0 getFormula() Use to retrieve a cell formula, will return the cell value if the cell doesn't contain a formula, or is not part of an array formula range. @@ -87,7 +89,7 @@ The following methods will be added in version 1.7.9 or is part of an array formula range or not. getArrayFormulaRange() Use to retrieve an array formula range. -The following methods will be changed in version 1.7.9 +The following methods will be changed in version 1.8.0 setValue() The logic behind this will be modified to store formula values in the new cell property structure, but it will still perform the same function. From af01842f786ccfd5e6d96a42166dca6fc2bb6b9a Mon Sep 17 00:00:00 2001 From: jgilliland Date: Tue, 16 Apr 2013 17:27:20 -0500 Subject: [PATCH 35/45] Remove empty row from empty charts and images --- Classes/PHPExcel/Writer/HTML.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index f50412e5..6c44ca40 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -520,9 +520,9 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]); if ($chartTL[1] > $rowMax) { $rowMax = $chartTL[1]; - } - if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { - $colMax = $chartTL[0]; + if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $chartTL[0]; + } } } } @@ -534,15 +534,15 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]); if ($imageTL[1] > $rowMax) { $rowMax = $imageTL[1]; - } - if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { - $colMax = $imageTL[0]; + if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $imageTL[0]; + } } } } $html = ''; $colMax++; - while ($row <= $rowMax) { + while ($row < $rowMax) { $html .= '
'; for ($col = 'A'; $col != $colMax; ++$col) { $html .= ', $tbodyStart = $rowMin; - $tbodyEnd = $rowMax; $theadStart = $theadEnd = 0; // default: no no if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); @@ -441,14 +440,12 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ if ($row == $theadEnd) { $html .= ' ' . PHP_EOL; } - - // ? - if ($row == $tbodyEnd) { - $html .= ' ' . PHP_EOL; - } } $html .= $this->_extendRowsForChartsAndImages($sheet, $row); + // Close table body. + $html .= ' ' . PHP_EOL; + // Write table footer $html .= $this->_generateTableFooter(); From e76673bcc084d48f2d7434362653be571d9cd76e Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sat, 20 Apr 2013 11:46:20 +0100 Subject: [PATCH 37/45] Bugfix: (Shanto) Work item GH-161 - Fix: Hyperlinks break when removing rows --- Classes/PHPExcel/ReferenceHelper.php | 4 +++- changelog.txt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index ef990bda..6fc96ecb 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -274,7 +274,9 @@ class PHPExcel_ReferenceHelper $pSheet->setComments($aNewComments); // replace the comments array // Update worksheet: hyperlinks - $aHyperlinkCollection = array_reverse($pSheet->getHyperlinkCollection(), true); + $aHyperlinkCollection = $pNumCols > 0 || $pNumRows > 0 ? + array_reverse($pSheet->getHyperlinkCollection(), true) : + $pSheet->getHyperlinkCollection(); foreach ($aHyperlinkCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { diff --git a/changelog.txt b/changelog.txt index 16a7ac10..bcdccbae 100644 --- a/changelog.txt +++ b/changelog.txt @@ -57,6 +57,7 @@ Fixed in develop branch for release v1.7.9: - Bugfix: (ccorliss) Work item GH-105 - Fixed number format fatal error - Bugfix: (MBaker) - Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers - Bugfix: (alexgann) Work item GH-154 - Fix merged-cell borders on HTML/PDF output +- Bugfix: (Shanto) Work item GH-161 - Fix: Hyperlinks break when removing rows -------------------------------------------------------------------------------- From ab01a6c6dc85842953d335821f66d3ce6525e353 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sat, 20 Apr 2013 23:53:25 +0100 Subject: [PATCH 38/45] Additional work on bugfix GH-161: Hyperlinks break when removing rows --- Classes/PHPExcel/ReferenceHelper.php | 27 ++++++++++++++++++++++++--- changelog.txt | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index 6fc96ecb..32b32784 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -68,6 +68,26 @@ class PHPExcel_ReferenceHelper protected function __construct() { } + private function cellSort($a, $b) { + list($ac,$ar) = sscanf($a,'%[A-Z]%d'); + list($bc,$br) = sscanf($b,'%[A-Z]%d'); + + if ($ar == $br) { + return strcasecmp(sprintf('%03s',$ac), sprintf('%03s',$bc)); + } + return ($ar < $br) ? -1 : 1; + } + + private function cellReverseSort($a, $b) { + list($ac,$ar) = sscanf($a,'%[A-Z]%d'); + list($bc,$br) = sscanf($b,'%[A-Z]%d'); + + if ($ar == $br) { + return 1 - strcasecmp(sprintf('%03s',$ac), sprintf('%03s',$bc)); + } + return ($ar < $br) ? 1 : -1; + } + /** * Insert a new column, updating all possible related data * @@ -274,9 +294,10 @@ class PHPExcel_ReferenceHelper $pSheet->setComments($aNewComments); // replace the comments array // Update worksheet: hyperlinks - $aHyperlinkCollection = $pNumCols > 0 || $pNumRows > 0 ? - array_reverse($pSheet->getHyperlinkCollection(), true) : - $pSheet->getHyperlinkCollection(); + $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aHyperlinkCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { diff --git a/changelog.txt b/changelog.txt index bcdccbae..cfe17493 100644 --- a/changelog.txt +++ b/changelog.txt @@ -58,6 +58,7 @@ Fixed in develop branch for release v1.7.9: - Bugfix: (MBaker) - Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers - Bugfix: (alexgann) Work item GH-154 - Fix merged-cell borders on HTML/PDF output - Bugfix: (Shanto) Work item GH-161 - Fix: Hyperlinks break when removing rows +- Bugfix: (neclimdul) Work item GH-166 - Fix Extra Table Row From Images and Charts -------------------------------------------------------------------------------- From 097ae1706eb3d82c9dab4f78c38cc54cd7921d77 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sun, 21 Apr 2013 16:03:25 +0100 Subject: [PATCH 39/45] Additional work on GH-161 - Fix: Hyperlinks break when removing rows --- Classes/PHPExcel/ReferenceHelper.php | 33 ++++++++++++---------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index 32b32784..8b986c08 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -73,7 +73,7 @@ class PHPExcel_ReferenceHelper list($bc,$br) = sscanf($b,'%[A-Z]%d'); if ($ar == $br) { - return strcasecmp(sprintf('%03s',$ac), sprintf('%03s',$bc)); + return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); } return ($ar < $br) ? -1 : 1; } @@ -83,7 +83,7 @@ class PHPExcel_ReferenceHelper list($bc,$br) = sscanf($b,'%[A-Z]%d'); if ($ar == $br) { - return 1 - strcasecmp(sprintf('%03s',$ac), sprintf('%03s',$bc)); + return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); } return ($ar < $br) ? 1 : -1; } @@ -106,7 +106,6 @@ class PHPExcel_ReferenceHelper list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); - // Clear cells if we are removing columns or rows $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); @@ -139,7 +138,6 @@ class PHPExcel_ReferenceHelper } } - // Loop through cells, bottom-up, and change cell coordinates while (($cellID = $remove ? array_shift($aCellCollection) : array_pop($aCellCollection))) { $cell = $pSheet->getCell($cellID); @@ -184,7 +182,6 @@ class PHPExcel_ReferenceHelper } } - // Duplicate styles for the newly inserted cells $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); @@ -236,7 +233,6 @@ class PHPExcel_ReferenceHelper } } - // Update worksheet: column dimensions $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); if (!empty($aColumnDimensions)) { @@ -250,7 +246,6 @@ class PHPExcel_ReferenceHelper $pSheet->refreshColumnDimensions(); } - // Update worksheet: row dimensions $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); if (!empty($aRowDimensions)) { @@ -273,9 +268,11 @@ class PHPExcel_ReferenceHelper } } - // Update worksheet: breaks - $aBreaks = array_reverse($pSheet->getBreaks(), true); + $aBreaks = $pSheet->getBreaks(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aBreaks as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { @@ -306,9 +303,11 @@ class PHPExcel_ReferenceHelper } } - // Update worksheet: data validations - $aDataValidationCollection = array_reverse($pSheet->getDataValidationCollection(), true); + $aDataValidationCollection = $pSheet->getDataValidationCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aDataValidationCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { @@ -317,7 +316,6 @@ class PHPExcel_ReferenceHelper } } - // Update worksheet: merge cells $aMergeCells = $pSheet->getMergeCells(); $aNewMergeCells = array(); // the new array of all merge cells @@ -327,9 +325,11 @@ class PHPExcel_ReferenceHelper } $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array - // Update worksheet: protected cells - $aProtectedCells = array_reverse($pSheet->getProtectedCells(), true); + $aProtectedCells = $pSheet->getProtectedCells(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aProtectedCells as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { @@ -338,7 +338,6 @@ class PHPExcel_ReferenceHelper } } - // Update worksheet: autofilter $autoFilter = $pSheet->getAutoFilter(); $autoFilterRange = $autoFilter->getRange(); @@ -397,19 +396,16 @@ class PHPExcel_ReferenceHelper $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); } - // Update worksheet: freeze pane if ($pSheet->getFreezePane() != '') { $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) ); } - // Page setup if ($pSheet->getPageSetup()->isPrintAreaSet()) { $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) ); } - // Update worksheet: drawings $aDrawings = $pSheet->getDrawingCollection(); foreach ($aDrawings as $objDrawing) { @@ -419,7 +415,6 @@ class PHPExcel_ReferenceHelper } } - // Update workbook: named ranges if (count($pSheet->getParent()->getNamedRanges()) > 0) { foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { From 15bfe6b8d544008a27d592606ba308bf6427636d Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sun, 21 Apr 2013 16:27:35 +0100 Subject: [PATCH 40/45] Update examples --- Examples/33chartcreate-area.php | 6 ++---- Examples/33chartcreate-bar-stacked.php | 6 ++---- Examples/33chartcreate-bar.php | 6 ++---- Examples/33chartcreate-column-2.php | 6 ++---- Examples/33chartcreate-column.php | 6 ++---- Examples/33chartcreate-composite-chart.php | 6 ++---- Examples/33chartcreate-line.php | 6 ++---- Examples/33chartcreate-multiple-charts.php | 6 ++---- Examples/33chartcreate-pie.php | 6 ++---- Examples/33chartcreate-radar.php | 6 ++---- 10 files changed, 20 insertions(+), 40 deletions(-) diff --git a/Examples/33chartcreate-area.php b/Examples/33chartcreate-area.php index 1e53b604..925ea0ad 100644 --- a/Examples/33chartcreate-area.php +++ b/Examples/33chartcreate-area.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-bar-stacked.php b/Examples/33chartcreate-bar-stacked.php index f6465ee7..0c604bb3 100644 --- a/Examples/33chartcreate-bar-stacked.php +++ b/Examples/33chartcreate-bar-stacked.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-bar.php b/Examples/33chartcreate-bar.php index 764942f0..daefd664 100644 --- a/Examples/33chartcreate-bar.php +++ b/Examples/33chartcreate-bar.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-column-2.php b/Examples/33chartcreate-column-2.php index 92104992..959712b5 100644 --- a/Examples/33chartcreate-column-2.php +++ b/Examples/33chartcreate-column-2.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-column.php b/Examples/33chartcreate-column.php index 6feacf9a..4c2dae64 100644 --- a/Examples/33chartcreate-column.php +++ b/Examples/33chartcreate-column.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-composite-chart.php b/Examples/33chartcreate-composite-chart.php index 14496f1c..a9785ff1 100644 --- a/Examples/33chartcreate-composite-chart.php +++ b/Examples/33chartcreate-composite-chart.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-line.php b/Examples/33chartcreate-line.php index 8fc9714e..4745982d 100644 --- a/Examples/33chartcreate-line.php +++ b/Examples/33chartcreate-line.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-multiple-charts.php b/Examples/33chartcreate-multiple-charts.php index a8943eec..041e03ae 100644 --- a/Examples/33chartcreate-multiple-charts.php +++ b/Examples/33chartcreate-multiple-charts.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-pie.php b/Examples/33chartcreate-pie.php index fe68ba2c..ce9825cb 100644 --- a/Examples/33chartcreate-pie.php +++ b/Examples/33chartcreate-pie.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); diff --git a/Examples/33chartcreate-radar.php b/Examples/33chartcreate-radar.php index a1bb413a..b3c226aa 100644 --- a/Examples/33chartcreate-radar.php +++ b/Examples/33chartcreate-radar.php @@ -36,11 +36,9 @@ date_default_timezone_set('Europe/London'); * @version ##VERSION##, ##DATE## */ -/** Include path **/ -set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/'); - /** PHPExcel */ -include 'PHPExcel.php'; +require_once '../Classes/PHPExcel.php'; + $objPHPExcel = new PHPExcel(); $objWorksheet = $objPHPExcel->getActiveSheet(); From db1fcd5cd6f7a85f0129c0daa0af53bc408fbe7c Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Tue, 23 Apr 2013 17:42:40 +0100 Subject: [PATCH 41/45] Additional work on GH-161 for Breaks --- Classes/PHPExcel/ReferenceHelper.php | 40 +++++++++++++++++----------- Classes/PHPExcel/Worksheet.php | 14 +++++++--- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index 8b986c08..5b17054d 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -68,7 +68,15 @@ class PHPExcel_ReferenceHelper protected function __construct() { } - private function cellSort($a, $b) { + public static function columnSort($a, $b) { + return strcasecmp(strlen($a) . $a, strlen($b) . $b); + } + + public static function columnReverseSort($a, $b) { + return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b); + } + + public static function cellSort($a, $b) { list($ac,$ar) = sscanf($a,'%[A-Z]%d'); list($bc,$br) = sscanf($b,'%[A-Z]%d'); @@ -78,7 +86,7 @@ class PHPExcel_ReferenceHelper return ($ar < $br) ? -1 : 1; } - private function cellReverseSort($a, $b) { + public static function cellReverseSort($a, $b) { list($ac,$ar) = sscanf($a,'%[A-Z]%d'); list($bc,$br) = sscanf($b,'%[A-Z]%d'); @@ -270,14 +278,14 @@ class PHPExcel_ReferenceHelper // Update worksheet: breaks $aBreaks = $pSheet->getBreaks(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aBreaks as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { - $pSheet->setBreak( $newReference, $value ); - $pSheet->setBreak( $key, PHPExcel_Worksheet::BREAK_NONE ); + $pSheet->setBreak($newReference, $value) + ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); } } @@ -292,9 +300,9 @@ class PHPExcel_ReferenceHelper // Update worksheet: hyperlinks $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aHyperlinkCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { @@ -305,9 +313,9 @@ class PHPExcel_ReferenceHelper // Update worksheet: data validations $aDataValidationCollection = $pSheet->getDataValidationCollection(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aDataValidationCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { @@ -327,9 +335,9 @@ class PHPExcel_ReferenceHelper // Update worksheet: protected cells $aProtectedCells = $pSheet->getProtectedCells(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); foreach ($aProtectedCells as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { diff --git a/Classes/PHPExcel/Worksheet.php b/Classes/PHPExcel/Worksheet.php index 9791ead2..51cb4e79 100644 --- a/Classes/PHPExcel/Worksheet.php +++ b/Classes/PHPExcel/Worksheet.php @@ -1604,7 +1604,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $pCell = strtoupper($pCell); if ($pCell != '') { - $this->_breaks[$pCell] = $pBreak; + if ($pBreak == PHPExcel_Worksheet::BREAK_NONE) { + if (isset($this->_breaks[$pCell])) { + unset($this->_breaks[$pCell]); + } + } else { + $this->_breaks[$pCell] = $pBreak; + } } else { throw new PHPExcel_Exception('No cell coordinate specified.'); } @@ -2432,9 +2438,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable if ($formatData) { $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( - $returnValue[$rRef][$cRef], - ($style->getNumberFormat()) ? - $style->getNumberFormat()->getFormatCode() : + $returnValue[$rRef][$cRef], + ($style->getNumberFormat()) ? + $style->getNumberFormat()->getFormatCode() : PHPExcel_Style_NumberFormat::FORMAT_GENERAL ); } From 7f7b5206522c21567fcb81bff77320b5c6613209 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Thu, 25 Apr 2013 17:53:29 +0100 Subject: [PATCH 42/45] Some refactoring of insert/delete row/column reference methods --- Classes/PHPExcel/Comment.php | 13 +- Classes/PHPExcel/ReferenceHelper.php | 261 +++++++++++------- .../Classes/PHPExcel/ReferenceHelperTest.php | 58 ++++ 3 files changed, 234 insertions(+), 98 deletions(-) create mode 100644 unitTests/Classes/PHPExcel/ReferenceHelperTest.php diff --git a/Classes/PHPExcel/Comment.php b/Classes/PHPExcel/Comment.php index 47db7ecd..e9f25781 100644 --- a/Classes/PHPExcel/Comment.php +++ b/Classes/PHPExcel/Comment.php @@ -106,10 +106,10 @@ class PHPExcel_Comment implements PHPExcel_IComparable public function __construct() { // Initialise variables - $this->_author = 'Author'; - $this->_text = new PHPExcel_RichText(); - $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); - $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + $this->_author = 'Author'; + $this->_text = new PHPExcel_RichText(); + $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); + $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; } /** @@ -314,4 +314,9 @@ class PHPExcel_Comment implements PHPExcel_IComparable } } } + + public function __toString() { + return $this->_text->getPlainText(); + } + } diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index 5b17054d..f301c559 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -96,22 +96,176 @@ class PHPExcel_ReferenceHelper return ($ar < $br) ? 1 : -1; } + private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { + list($cellColumn, $cellRow) = PHPExcel_Cell::coordinateFromString($cellAddress); + $cellColumnIndex = PHPExcel_Cell::columnIndexFromString($cellColumn); + // Is cell within the range of rows/columns if we're deleting + if ($pNumRows < 0 && + ($cellRow >= ($beforeRow + $pNumRows)) && + ($cellRow < $beforeRow)) { + return TRUE; + } elseif ($pNumCols < 0 && + ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) && + ($cellColumnIndex < $beforeColumnIndex)) { + return TRUE; + } + return FALSE; + } + + protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aBreaks = $pSheet->getBreaks(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aBreaks as $key => $value) { + if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // If we're deleting, then clear any defined breaks that are within the range + // of rows/columns that we're deleting + $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } else { + // Otherwise update any affected breaks by inserting a new break at the appropriate point + // and removing the old affected break + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setBreak($newReference, $value) + ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } + } + } + } + + protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aComments = $pSheet->getComments(); + $aNewComments = array(); // the new array of all comments + + foreach ($aComments as $key => &$value) { + // Any comments inside a deleted range will be ignored + if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // Otherwise build a new array of comments indexed by the adjusted cell reference + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewComments[$newReference] = $value; + } + } + // Replace the comments array with the new set of comments + $pSheet->setComments($aNewComments); + } + + protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aHyperlinkCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setHyperlink( $newReference, $value ); + $pSheet->setHyperlink( $key, null ); + } + } + } + + protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aDataValidationCollection = $pSheet->getDataValidationCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aDataValidationCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setDataValidation( $newReference, $value ); + $pSheet->setDataValidation( $key, null ); + } + } + } + + protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewMergeCells[$newReference] = $newReference; + } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array + } + + protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aProtectedCells = $pSheet->getProtectedCells(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aProtectedCells as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->protectCells( $newReference, $value, true ); + $pSheet->unprotectCells( $key ); + } + } + } + + protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); + if (!empty($aColumnDimensions)) { + foreach ($aColumnDimensions as $objColumnDimension) { + $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); + list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objColumnDimension->getColumnIndex() != $newReference) { + $objColumnDimension->setColumnIndex($newReference); + } + } + $pSheet->refreshColumnDimensions(); + } + } + + protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); + if (!empty($aRowDimensions)) { + foreach ($aRowDimensions as $objRowDimension) { + $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); + list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objRowDimension->getRowIndex() != $newReference) { + $objRowDimension->setRowIndex($newReference); + } + } + $pSheet->refreshRowDimensions(); + + $copyDimension = $pSheet->getRowDimension($beforeRow - 1); + for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { + $newDimension = $pSheet->getRowDimension($i); + $newDimension->setRowHeight($copyDimension->getRowHeight()); + $newDimension->setVisible($copyDimension->getVisible()); + $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); + $newDimension->setCollapsed($copyDimension->getCollapsed()); + } + } + } + /** - * Insert a new column, updating all possible related data + * Insert a new column or row, updating all possible related data * * @param int $pBefore Insert before this one * @param int $pNumCols Number of columns to insert * @param int $pNumRows Number of rows to insert * @throws PHPExcel_Exception */ - public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) + { $remove = ($pNumCols < 0 || $pNumRows < 0); $aCellCollection = $pSheet->getCellCollection(); // Get coordinates of $pBefore $beforeColumn = 'A'; $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); // Clear cells if we are removing columns or rows @@ -242,109 +396,28 @@ class PHPExcel_ReferenceHelper } // Update worksheet: column dimensions - $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); - if (!empty($aColumnDimensions)) { - foreach ($aColumnDimensions as $objColumnDimension) { - $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); - list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); - if ($objColumnDimension->getColumnIndex() != $newReference) { - $objColumnDimension->setColumnIndex($newReference); - } - } - $pSheet->refreshColumnDimensions(); - } + $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: row dimensions - $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); - if (!empty($aRowDimensions)) { - foreach ($aRowDimensions as $objRowDimension) { - $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); - list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); - if ($objRowDimension->getRowIndex() != $newReference) { - $objRowDimension->setRowIndex($newReference); - } - } - $pSheet->refreshRowDimensions(); + $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - $copyDimension = $pSheet->getRowDimension($beforeRow - 1); - for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { - $newDimension = $pSheet->getRowDimension($i); - $newDimension->setRowHeight($copyDimension->getRowHeight()); - $newDimension->setVisible($copyDimension->getVisible()); - $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); - $newDimension->setCollapsed($copyDimension->getCollapsed()); - } - } + // Update worksheet: page breaks + $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - // Update worksheet: breaks - $aBreaks = $pSheet->getBreaks(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aBreaks as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setBreak($newReference, $value) - ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); - } - } - - // Update worksheet: comments - $aComments = $pSheet->getComments(); - $aNewComments = array(); // the new array of all comments - foreach ($aComments as $key => &$value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - $aNewComments[$newReference] = $value; - } - $pSheet->setComments($aNewComments); // replace the comments array + // Update worksheet: comments + $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: hyperlinks - $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aHyperlinkCollection as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setHyperlink( $newReference, $value ); - $pSheet->setHyperlink( $key, null ); - } - } + $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: data validations - $aDataValidationCollection = $pSheet->getDataValidationCollection(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aDataValidationCollection as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setDataValidation( $newReference, $value ); - $pSheet->setDataValidation( $key, null ); - } - } + $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: merge cells - $aMergeCells = $pSheet->getMergeCells(); - $aNewMergeCells = array(); // the new array of all merge cells - foreach ($aMergeCells as $key => &$value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - $aNewMergeCells[$newReference] = $newReference; - } - $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array + $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: protected cells - $aProtectedCells = $pSheet->getProtectedCells(); - ($pNumCols > 0 || $pNumRows > 0) ? - uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : - uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); - foreach ($aProtectedCells as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->protectCells( $newReference, $value, true ); - $pSheet->unprotectCells( $key ); - } - } + $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: autofilter $autoFilter = $pSheet->getAutoFilter(); diff --git a/unitTests/Classes/PHPExcel/ReferenceHelperTest.php b/unitTests/Classes/PHPExcel/ReferenceHelperTest.php new file mode 100644 index 00000000..f37db692 --- /dev/null +++ b/unitTests/Classes/PHPExcel/ReferenceHelperTest.php @@ -0,0 +1,58 @@ + $value) { + $this->assertEquals($columnExpectedResult[$key], $value); + } + } + + public function testColumnReverseSort() + { + $columnBase = $columnExpectedResult = array( + 'A','B','Z', + 'AA','AB','AZ', + 'BA','BB','BZ', + 'ZA','ZB','ZZ', + 'AAA','AAB','AAZ', + 'ABA','ABB','ABZ', + 'AZA','AZB','AZZ', + 'BAA','BAB','BAZ', + 'BBA','BBB','BBZ', + 'BZA','BZB','BZZ' + ); + shuffle($columnBase); + $columnExpectedResult = array_reverse($columnExpectedResult); + usort($columnBase, array('PHPExcel_ReferenceHelper','columnReverseSort')); + foreach($columnBase as $key => $value) { + $this->assertEquals($columnExpectedResult[$key], $value); + } + } + +} From d96364fda65ef361f01090d49e1a47a984518b62 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Thu, 25 Apr 2013 23:44:15 +0100 Subject: [PATCH 43/45] PHPDoc blocks --- Classes/PHPExcel/ReferenceHelper.php | 99 ++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index f301c559..f6deb042 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -96,6 +96,16 @@ class PHPExcel_ReferenceHelper return ($ar < $br) ? 1 : -1; } + /** + * Test whether a cell address falls within a defined range of cells + * + * @param string $cellAddress Address of the cell we're testing + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @return boolean + */ private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { list($cellColumn, $cellRow) = PHPExcel_Cell::coordinateFromString($cellAddress); $cellColumnIndex = PHPExcel_Cell::columnIndexFromString($cellColumn); @@ -112,6 +122,16 @@ class PHPExcel_ReferenceHelper return FALSE; } + /** + * Update page breaks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aBreaks = $pSheet->getBreaks(); @@ -136,6 +156,16 @@ class PHPExcel_ReferenceHelper } } + /** + * Update cell comments when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aComments = $pSheet->getComments(); @@ -153,6 +183,16 @@ class PHPExcel_ReferenceHelper $pSheet->setComments($aNewComments); } + /** + * Update hyperlinks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); @@ -169,6 +209,16 @@ class PHPExcel_ReferenceHelper } } + /** + * Update data validations when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aDataValidationCollection = $pSheet->getDataValidationCollection(); @@ -184,6 +234,16 @@ class PHPExcel_ReferenceHelper } } + /** + * Update merged cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aMergeCells = $pSheet->getMergeCells(); @@ -195,6 +255,16 @@ class PHPExcel_ReferenceHelper $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array } + /** + * Update protected cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aProtectedCells = $pSheet->getProtectedCells(); @@ -210,6 +280,16 @@ class PHPExcel_ReferenceHelper } } + /** + * Update column dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); @@ -225,6 +305,16 @@ class PHPExcel_ReferenceHelper } } + /** + * Update row dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) { $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); @@ -252,10 +342,11 @@ class PHPExcel_ReferenceHelper /** * Insert a new column or row, updating all possible related data * - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @throws PHPExcel_Exception + * @param string $pBefore Insert before this cell address (e.g. 'A1') + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @throws PHPExcel_Exception */ public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) { From 8a05ee88964a659fd66d2f730deba519a6c6a0c9 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 26 Apr 2013 07:46:50 +0100 Subject: [PATCH 44/45] Added Docblocks for cell address and column sort callback functions --- Classes/PHPExcel/ReferenceHelper.php | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index f6deb042..6f8c1d43 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -68,14 +68,38 @@ class PHPExcel_ReferenceHelper protected function __construct() { } + /** + * Compare two column addresses + * Intended for use as a Callback function for sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ public static function columnSort($a, $b) { return strcasecmp(strlen($a) . $a, strlen($b) . $b); } + /** + * Compare two column addresses + * Intended for use as a Callback function for reverse sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ public static function columnReverseSort($a, $b) { return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b); } + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ public static function cellSort($a, $b) { list($ac,$ar) = sscanf($a,'%[A-Z]%d'); list($bc,$br) = sscanf($b,'%[A-Z]%d'); @@ -86,6 +110,14 @@ class PHPExcel_ReferenceHelper return ($ar < $br) ? -1 : 1; } + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ public static function cellReverseSort($a, $b) { list($ac,$ar) = sscanf($a,'%[A-Z]%d'); list($bc,$br) = sscanf($b,'%[A-Z]%d'); From 8debf76a8a58131da6f3f82fe792359123dcb1bc Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 26 Apr 2013 12:44:47 +0100 Subject: [PATCH 45/45] Minor performance tweaks --- Classes/PHPExcel/CachedObjectStorage/CacheBase.php | 8 ++++---- Classes/PHPExcel/Calculation.php | 4 ++-- Classes/PHPExcel/Cell.php | 6 +++--- Classes/PHPExcel/ReferenceHelper.php | 10 +++++----- Classes/PHPExcel/Worksheet/AutoFilter.php | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php index 6dd6c1a5..c4b57817 100644 --- a/Classes/PHPExcel/CachedObjectStorage/CacheBase.php +++ b/Classes/PHPExcel/CachedObjectStorage/CacheBase.php @@ -177,7 +177,7 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { public function getSortedCellList() { $sortKeys = array(); foreach ($this->getCellList() as $coord) { - list($column,$row) = sscanf($coord,'%[A-Z]%d'); + sscanf($coord,'%[A-Z]%d', $column, $row); $sortKeys[sprintf('%09d%3s',$row,$column)] = $coord; } ksort($sortKeys); @@ -198,7 +198,7 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { $col = array('A' => '1A'); $row = array(1); foreach ($this->getCellList() as $coord) { - list($c,$r) = sscanf($coord,'%[A-Z]%d'); + sscanf($coord,'%[A-Z]%d', $c, $r); $row[$r] = $r; $col[$c] = strlen($c).$c; } @@ -221,13 +221,13 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { public function getCurrentColumn() { - list($column,$row) = sscanf($this->_currentObjectID, '%[A-Z]%d'); + sscanf($this->_currentObjectID, '%[A-Z]%d', $column, $row); return $column; } public function getCurrentRow() { - list($column,$row) = sscanf($this->_currentObjectID, '%[A-Z]%d'); + sscanf($this->_currentObjectID, '%[A-Z]%d', $column, $row); return $row; } diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index c98e50cb..93f77d74 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -3621,7 +3621,7 @@ class PHPExcel_Calculation { $pRange = $pSheetName.'!'.$pRange; if (!isset($aReferences[1])) { // Single cell in range - list($currentCol,$currentRow) = sscanf($aReferences[0],'%[A-Z]%d'); + sscanf($aReferences[0],'%[A-Z]%d', $currentCol, $currentRow); $cellValue = NULL; if ($pSheet->cellExists($aReferences[0])) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); @@ -3632,7 +3632,7 @@ class PHPExcel_Calculation { // Extract cell data for all cells in the range foreach ($aReferences as $reference) { // Extract range - list($currentCol,$currentRow) = sscanf($reference,'%[A-Z]%d'); + sscanf($reference,'%[A-Z]%d', $currentCol, $currentRow); $cellValue = NULL; if ($pSheet->cellExists($reference)) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); diff --git a/Classes/PHPExcel/Cell.php b/Classes/PHPExcel/Cell.php index dbd7a822..27fb9147 100644 --- a/Classes/PHPExcel/Cell.php +++ b/Classes/PHPExcel/Cell.php @@ -822,8 +822,8 @@ class PHPExcel_Cell // Range... list($rangeStart, $rangeEnd) = $range; - list($startCol, $startRow) = sscanf($rangeStart,'%[A-Z]%d'); - list($endCol, $endRow) = sscanf($rangeEnd,'%[A-Z]%d'); + sscanf($rangeStart,'%[A-Z]%d', $startCol, $startRow); + sscanf($rangeEnd,'%[A-Z]%d', $endCol, $endRow); $endCol++; // Current data @@ -845,7 +845,7 @@ class PHPExcel_Cell // Sort the result by column and row $sortKeys = array(); foreach (array_unique($returnValue) as $coord) { - list($column,$row) = sscanf($coord,'%[A-Z]%d'); + sscanf($coord,'%[A-Z]%d', $column, $row); $sortKeys[sprintf('%3s%09d',$column,$row)] = $coord; } ksort($sortKeys); diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index 6f8c1d43..94f21b32 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -101,8 +101,8 @@ class PHPExcel_ReferenceHelper * @return integer */ public static function cellSort($a, $b) { - list($ac,$ar) = sscanf($a,'%[A-Z]%d'); - list($bc,$br) = sscanf($b,'%[A-Z]%d'); + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); if ($ar == $br) { return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); @@ -119,8 +119,8 @@ class PHPExcel_ReferenceHelper * @return integer */ public static function cellReverseSort($a, $b) { - list($ac,$ar) = sscanf($a,'%[A-Z]%d'); - list($bc,$br) = sscanf($b,'%[A-Z]%d'); + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); if ($ar == $br) { return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); @@ -549,7 +549,7 @@ class PHPExcel_ReferenceHelper if ($pNumCols != 0) { $autoFilterColumns = array_keys($autoFilter->getColumns()); if (count($autoFilterColumns) > 0) { - list($column,$row) = sscanf($pBefore,'%[A-Z]%d'); + sscanf($pBefore,'%[A-Z]%d', $column, $row); $columnIndex = PHPExcel_Cell::columnIndexFromString($column); list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); if ($columnIndex <= $rangeEnd[0]) { diff --git a/Classes/PHPExcel/Worksheet/AutoFilter.php b/Classes/PHPExcel/Worksheet/AutoFilter.php index c39bfbf8..ae05875e 100644 --- a/Classes/PHPExcel/Worksheet/AutoFilter.php +++ b/Classes/PHPExcel/Worksheet/AutoFilter.php @@ -725,7 +725,7 @@ class PHPExcel_Worksheet_AutoFilter // Date based if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') { // Month or Quarter - list($periodType,$period) = sscanf($dynamicRuleType,'%[A-Z]%d'); + sscanf($dynamicRuleType,'%[A-Z]%d', $periodType, $period); if ($periodType == 'M') { $ruleValues = array($period); } else {
'; From 0a09b235eeb0bf7bc66a4d49148cc168ad40f82c Mon Sep 17 00:00:00 2001 From: jgilliland Date: Tue, 16 Apr 2013 17:29:19 -0500 Subject: [PATCH 36/45] Close tbody after images and charts --- Classes/PHPExcel/Writer/HTML.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index 6c44ca40..87445698 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -394,7 +394,6 @@ class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_ // calculate start of