@ -0,0 +1,3 @@ | |||
/Build export-ignore | |||
/unitTests export-ignore | |||
README.md export-ignore |
@ -0,0 +1,9 @@ | |||
build/PHPExcel.phar | |||
unitTests/codeCoverage | |||
analysis | |||
## IDE support | |||
*.buildpath | |||
*.project | |||
/.settings | |||
/.idea |
@ -0,0 +1,29 @@ | |||
language: php | |||
php: | |||
- 5.4 | |||
- 5.5 | |||
- 5.6 | |||
- 7.0 | |||
- hhvm | |||
matrix: | |||
allow_failures: | |||
- php: hhvm | |||
before_script: | |||
## Packages | |||
- sudo apt-get -qq update > /dev/null | |||
## Composer | |||
- composer self-update | |||
- composer install --prefer-source --dev | |||
- phpenv global "$TRAVIS_PHP_VERSION" | |||
script: | |||
## PHP_CodeSniffer | |||
- ./vendor/bin/phpcs --report-width=200 --report-summary --report-full Classes/ unitTests/ --standard=PSR2 -n | |||
## PHPUnit | |||
- phpunit -c ./unitTests/ | |||
notifications: | |||
email: false |
@ -0,0 +1,289 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_IOFactory | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_IOFactory | |||
{ | |||
/** | |||
* Search locations | |||
* | |||
* @var array | |||
* @access private | |||
* @static | |||
*/ | |||
private static $searchLocations = array( | |||
array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), | |||
array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) | |||
); | |||
/** | |||
* Autoresolve classes | |||
* | |||
* @var array | |||
* @access private | |||
* @static | |||
*/ | |||
private static $autoResolveClasses = array( | |||
'Excel2007', | |||
'Excel5', | |||
'Excel2003XML', | |||
'OOCalc', | |||
'SYLK', | |||
'Gnumeric', | |||
'HTML', | |||
'CSV', | |||
); | |||
/** | |||
* Private constructor for PHPExcel_IOFactory | |||
*/ | |||
private function __construct() | |||
{ | |||
} | |||
/** | |||
* Get search locations | |||
* | |||
* @static | |||
* @access public | |||
* @return array | |||
*/ | |||
public static function getSearchLocations() | |||
{ | |||
return self::$searchLocations; | |||
} | |||
/** | |||
* Set search locations | |||
* | |||
* @static | |||
* @access public | |||
* @param array $value | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function setSearchLocations($value) | |||
{ | |||
if (is_array($value)) { | |||
self::$searchLocations = $value; | |||
} else { | |||
throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); | |||
} | |||
} | |||
/** | |||
* Add search location | |||
* | |||
* @static | |||
* @access public | |||
* @param string $type Example: IWriter | |||
* @param string $location Example: PHPExcel/Writer/{0}.php | |||
* @param string $classname Example: PHPExcel_Writer_{0} | |||
*/ | |||
public static function addSearchLocation($type = '', $location = '', $classname = '') | |||
{ | |||
self::$searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); | |||
} | |||
/** | |||
* Create PHPExcel_Writer_IWriter | |||
* | |||
* @static | |||
* @access public | |||
* @param PHPExcel $phpExcel | |||
* @param string $writerType Example: Excel2007 | |||
* @return PHPExcel_Writer_IWriter | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createWriter(PHPExcel $phpExcel, $writerType = '') | |||
{ | |||
// Search type | |||
$searchType = 'IWriter'; | |||
// Include class | |||
foreach (self::$searchLocations as $searchLocation) { | |||
if ($searchLocation['type'] == $searchType) { | |||
$className = str_replace('{0}', $writerType, $searchLocation['class']); | |||
$instance = new $className($phpExcel); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
} | |||
// Nothing found... | |||
throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); | |||
} | |||
/** | |||
* Create PHPExcel_Reader_IReader | |||
* | |||
* @static | |||
* @access public | |||
* @param string $readerType Example: Excel2007 | |||
* @return PHPExcel_Reader_IReader | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createReader($readerType = '') | |||
{ | |||
// Search type | |||
$searchType = 'IReader'; | |||
// Include class | |||
foreach (self::$searchLocations as $searchLocation) { | |||
if ($searchLocation['type'] == $searchType) { | |||
$className = str_replace('{0}', $readerType, $searchLocation['class']); | |||
$instance = new $className(); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
} | |||
// Nothing found... | |||
throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); | |||
} | |||
/** | |||
* Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function load($pFilename) | |||
{ | |||
$reader = self::createReaderForFile($pFilename); | |||
return $reader->load($pFilename); | |||
} | |||
/** | |||
* Identify file type using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file to identify | |||
* @return string | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function identify($pFilename) | |||
{ | |||
$reader = self::createReaderForFile($pFilename); | |||
$className = get_class($reader); | |||
$classType = explode('_', $className); | |||
unset($reader); | |||
return array_pop($classType); | |||
} | |||
/** | |||
* Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file | |||
* @return PHPExcel_Reader_IReader | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createReaderForFile($pFilename) | |||
{ | |||
// First, lucky guess by inspecting file extension | |||
$pathinfo = pathinfo($pFilename); | |||
$extensionType = null; | |||
if (isset($pathinfo['extension'])) { | |||
switch (strtolower($pathinfo['extension'])) { | |||
case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet | |||
case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded) | |||
case 'xltx': // Excel (OfficeOpenXML) Template | |||
case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded) | |||
$extensionType = 'Excel2007'; | |||
break; | |||
case 'xls': // Excel (BIFF) Spreadsheet | |||
case 'xlt': // Excel (BIFF) Template | |||
$extensionType = 'Excel5'; | |||
break; | |||
case 'ods': // Open/Libre Offic Calc | |||
case 'ots': // Open/Libre Offic Calc Template | |||
$extensionType = 'OOCalc'; | |||
break; | |||
case 'slk': | |||
$extensionType = 'SYLK'; | |||
break; | |||
case 'xml': // Excel 2003 SpreadSheetML | |||
$extensionType = 'Excel2003XML'; | |||
break; | |||
case 'gnumeric': | |||
$extensionType = 'Gnumeric'; | |||
break; | |||
case 'htm': | |||
case 'html': | |||
$extensionType = 'HTML'; | |||
break; | |||
case 'csv': | |||
// Do nothing | |||
// We must not try to use CSV reader since it loads | |||
// all files including Excel files etc. | |||
break; | |||
default: | |||
break; | |||
} | |||
if ($extensionType !== null) { | |||
$reader = self::createReader($extensionType); | |||
// Let's see if we are lucky | |||
if (isset($reader) && $reader->canRead($pFilename)) { | |||
return $reader; | |||
} | |||
} | |||
} | |||
// If we reach here then "lucky guess" didn't give any result | |||
// Try walking through all the options in self::$autoResolveClasses | |||
foreach (self::$autoResolveClasses as $autoResolveClass) { | |||
// Ignore our original guess, we know that won't work | |||
if ($autoResolveClass !== $extensionType) { | |||
$reader = self::createReader($autoResolveClass); | |||
if ($reader->canRead($pFilename)) { | |||
return $reader; | |||
} | |||
} | |||
} | |||
throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); | |||
} | |||
} |
@ -0,0 +1,81 @@ | |||
<?php | |||
PHPExcel_Autoloader::register(); | |||
// As we always try to run the autoloader before anything else, we can use it to do a few | |||
// simple checks and initialisations | |||
//PHPExcel_Shared_ZipStreamWrapper::register(); | |||
// check mbstring.func_overload | |||
if (ini_get('mbstring.func_overload') & 2) { | |||
throw new PHPExcel_Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); | |||
} | |||
PHPExcel_Shared_String::buildCharacterSets(); | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Autoloader | |||
{ | |||
/** | |||
* Register the Autoloader with SPL | |||
* | |||
*/ | |||
public static function register() | |||
{ | |||
if (function_exists('__autoload')) { | |||
// Register any existing autoloader function with SPL, so we don't get any clashes | |||
spl_autoload_register('__autoload'); | |||
} | |||
// Register ourselves with SPL | |||
if (version_compare(PHP_VERSION, '5.3.0') >= 0) { | |||
return spl_autoload_register(array('PHPExcel_Autoloader', 'load'), true, true); | |||
} else { | |||
return spl_autoload_register(array('PHPExcel_Autoloader', 'load')); | |||
} | |||
} | |||
/** | |||
* Autoload a class identified by name | |||
* | |||
* @param string $pClassName Name of the object to load | |||
*/ | |||
public static function load($pClassName) | |||
{ | |||
if ((class_exists($pClassName, false)) || (strpos($pClassName, 'PHPExcel') !== 0)) { | |||
// Either already loaded, or not a PHPExcel class request | |||
return false; | |||
} | |||
$pClassFilePath = PHPEXCEL_ROOT . | |||
str_replace('_', DIRECTORY_SEPARATOR, $pClassName) . | |||
'.php'; | |||
if ((file_exists($pClassFilePath) === false) || (is_readable($pClassFilePath) === false)) { | |||
// Can't load | |||
return false; | |||
} | |||
require($pClassFilePath); | |||
} | |||
} |
@ -0,0 +1,290 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_APC | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_APC extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Prefix used to uniquely identify cache data for this worksheet | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
private $cachePrefix = null; | |||
/** | |||
* Cache timeout | |||
* | |||
* @access private | |||
* @var integer | |||
*/ | |||
private $cacheTime = 600; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @access private | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
if (!apc_store( | |||
$this->cachePrefix . $this->currentObjectID . '.cache', | |||
serialize($this->currentObject), | |||
$this->cacheTime | |||
)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception('Failed to store cell ' . $this->currentObjectID . ' in APC'); | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @access public | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->cellCache[$pCoord] = true; | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? | |||
* | |||
* @access public | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @throws PHPExcel_Exception | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord) | |||
{ | |||
// Check if the requested entry is the current object, or exists in the cache | |||
if (parent::isDataSet($pCoord)) { | |||
if ($this->currentObjectID == $pCoord) { | |||
return true; | |||
} | |||
// Check if the requested entry still exists in apc | |||
$success = apc_fetch($this->cachePrefix.$pCoord.'.cache'); | |||
if ($success === false) { | |||
// Entry no longer exists in APC, so clear it from the cache array | |||
parent::deleteCacheData($pCoord); | |||
throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache'); | |||
} | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @access public | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (parent::isDataSet($pCoord)) { | |||
$obj = apc_fetch($this->cachePrefix . $pCoord . '.cache'); | |||
if ($obj === false) { | |||
// Entry no longer exists in APC, so clear it from the cache array | |||
parent::deleteCacheData($pCoord); | |||
throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache'); | |||
} | |||
} else { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = unserialize($obj); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @access public | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord) | |||
{ | |||
// Delete the entry from APC | |||
apc_delete($this->cachePrefix.$pCoord.'.cache'); | |||
// Delete the entry from our cell address array | |||
parent::deleteCacheData($pCoord); | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @access public | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @throws PHPExcel_Exception | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::copyCellCollection($parent); | |||
// Get a new id for the new file name | |||
$baseUnique = $this->getUniqueID(); | |||
$newCachePrefix = substr(md5($baseUnique), 0, 8) . '.'; | |||
$cacheList = $this->getCellList(); | |||
foreach ($cacheList as $cellID) { | |||
if ($cellID != $this->currentObjectID) { | |||
$obj = apc_fetch($this->cachePrefix . $cellID . '.cache'); | |||
if ($obj === false) { | |||
// Entry no longer exists in APC, so clear it from the cache array | |||
parent::deleteCacheData($cellID); | |||
throw new PHPExcel_Exception('Cell entry ' . $cellID . ' no longer exists in APC'); | |||
} | |||
if (!apc_store($newCachePrefix . $cellID . '.cache', $obj, $this->cacheTime)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception('Failed to store cell ' . $cellID . ' in APC'); | |||
} | |||
} | |||
} | |||
$this->cachePrefix = $newCachePrefix; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if ($this->currentObject !== null) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
// Flush the APC cache | |||
$this->__destruct(); | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
* @param array of mixed $arguments Additional initialisation arguments | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent, $arguments) | |||
{ | |||
$cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; | |||
if ($this->cachePrefix === null) { | |||
$baseUnique = $this->getUniqueID(); | |||
$this->cachePrefix = substr(md5($baseUnique), 0, 8) . '.'; | |||
$this->cacheTime = $cacheTime; | |||
parent::__construct($parent); | |||
} | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
$cacheList = $this->getCellList(); | |||
foreach ($cacheList as $cellID) { | |||
apc_delete($this->cachePrefix . $cellID . '.cache'); | |||
} | |||
} | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
if (!function_exists('apc_store')) { | |||
return false; | |||
} | |||
if (apc_sma_info() === false) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@ -0,0 +1,368 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_CacheBase | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
abstract class PHPExcel_CachedObjectStorage_CacheBase | |||
{ | |||
/** | |||
* Parent worksheet | |||
* | |||
* @var PHPExcel_Worksheet | |||
*/ | |||
protected $parent; | |||
/** | |||
* The currently active Cell | |||
* | |||
* @var PHPExcel_Cell | |||
*/ | |||
protected $currentObject = null; | |||
/** | |||
* Coordinate address of the currently active Cell | |||
* | |||
* @var string | |||
*/ | |||
protected $currentObjectID = null; | |||
/** | |||
* Flag indicating whether the currently active Cell requires saving | |||
* | |||
* @var boolean | |||
*/ | |||
protected $currentCellIsDirty = true; | |||
/** | |||
* An array of cells or cell pointers for the worksheet cells held in this cache, | |||
* and indexed by their coordinate address within the worksheet | |||
* | |||
* @var array of mixed | |||
*/ | |||
protected $cellCache = array(); | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent) | |||
{ | |||
// Set our parent worksheet. | |||
// This is maintained within the cache controller to facilitate re-attaching it to PHPExcel_Cell objects when | |||
// they are woken from a serialized state | |||
$this->parent = $parent; | |||
} | |||
/** | |||
* Return the parent worksheet for this cell collection | |||
* | |||
* @return PHPExcel_Worksheet | |||
*/ | |||
public function getParent() | |||
{ | |||
return $this->parent; | |||
} | |||
/** | |||
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? | |||
* | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return true; | |||
} | |||
// Check if the requested entry exists in the cache | |||
return isset($this->cellCache[$pCoord]); | |||
} | |||
/** | |||
* Move a cell object from one address to another | |||
* | |||
* @param string $fromAddress Current address of the cell to move | |||
* @param string $toAddress Destination address of the cell to move | |||
* @return boolean | |||
*/ | |||
public function moveCell($fromAddress, $toAddress) | |||
{ | |||
if ($fromAddress === $this->currentObjectID) { | |||
$this->currentObjectID = $toAddress; | |||
} | |||
$this->currentCellIsDirty = true; | |||
if (isset($this->cellCache[$fromAddress])) { | |||
$this->cellCache[$toAddress] = &$this->cellCache[$fromAddress]; | |||
unset($this->cellCache[$fromAddress]); | |||
} | |||
return true; | |||
} | |||
/** | |||
* Add or Update a cell in cache | |||
* | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function updateCacheData(PHPExcel_Cell $cell) | |||
{ | |||
return $this->addCacheData($cell->getCoordinate(), $cell); | |||
} | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID && !is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
if (is_object($this->cellCache[$pCoord])) { | |||
$this->cellCache[$pCoord]->detach(); | |||
unset($this->cellCache[$pCoord]); | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
return array_keys($this->cellCache); | |||
} | |||
/** | |||
* Sort the list of all cell addresses currently held in cache by row and column | |||
* | |||
* @return string[] | |||
*/ | |||
public function getSortedCellList() | |||
{ | |||
$sortKeys = array(); | |||
foreach ($this->getCellList() as $coord) { | |||
sscanf($coord, '%[A-Z]%d', $column, $row); | |||
$sortKeys[sprintf('%09d%3s', $row, $column)] = $coord; | |||
} | |||
ksort($sortKeys); | |||
return array_values($sortKeys); | |||
} | |||
/** | |||
* Get highest worksheet column and highest row that have cell records | |||
* | |||
* @return array Highest column name and highest row number | |||
*/ | |||
public function getHighestRowAndColumn() | |||
{ | |||
// Lookup highest column and highest row | |||
$col = array('A' => '1A'); | |||
$row = array(1); | |||
foreach ($this->getCellList() as $coord) { | |||
sscanf($coord, '%[A-Z]%d', $c, $r); | |||
$row[$r] = $r; | |||
$col[$c] = strlen($c).$c; | |||
} | |||
if (!empty($row)) { | |||
// Determine highest column and row | |||
$highestRow = max($row); | |||
$highestColumn = substr(max($col), 1); | |||
} | |||
return array( | |||
'row' => $highestRow, | |||
'column' => $highestColumn | |||
); | |||
} | |||
/** | |||
* Return the cell address of the currently active cell object | |||
* | |||
* @return string | |||
*/ | |||
public function getCurrentAddress() | |||
{ | |||
return $this->currentObjectID; | |||
} | |||
/** | |||
* Return the column address of the currently active cell object | |||
* | |||
* @return string | |||
*/ | |||
public function getCurrentColumn() | |||
{ | |||
sscanf($this->currentObjectID, '%[A-Z]%d', $column, $row); | |||
return $column; | |||
} | |||
/** | |||
* Return the row address of the currently active cell object | |||
* | |||
* @return integer | |||
*/ | |||
public function getCurrentRow() | |||
{ | |||
sscanf($this->currentObjectID, '%[A-Z]%d', $column, $row); | |||
return (integer) $row; | |||
} | |||
/** | |||
* Get highest worksheet column | |||
* | |||
* @param string $row Return the highest column for the specified row, | |||
* or the highest column of any row if no row number is passed | |||
* @return string Highest column name | |||
*/ | |||
public function getHighestColumn($row = null) | |||
{ | |||
if ($row == null) { | |||
$colRow = $this->getHighestRowAndColumn(); | |||
return $colRow['column']; | |||
} | |||
$columnList = array(1); | |||
foreach ($this->getCellList() as $coord) { | |||
sscanf($coord, '%[A-Z]%d', $c, $r); | |||
if ($r != $row) { | |||
continue; | |||
} | |||
$columnList[] = PHPExcel_Cell::columnIndexFromString($c); | |||
} | |||
return PHPExcel_Cell::stringFromColumnIndex(max($columnList) - 1); | |||
} | |||
/** | |||
* Get highest worksheet row | |||
* | |||
* @param string $column Return the highest row for the specified column, | |||
* or the highest row of any column if no column letter is passed | |||
* @return int Highest row number | |||
*/ | |||
public function getHighestRow($column = null) | |||
{ | |||
if ($column == null) { | |||
$colRow = $this->getHighestRowAndColumn(); | |||
return $colRow['row']; | |||
} | |||
$rowList = array(0); | |||
foreach ($this->getCellList() as $coord) { | |||
sscanf($coord, '%[A-Z]%d', $c, $r); | |||
if ($c != $column) { | |||
continue; | |||
} | |||
$rowList[] = $r; | |||
} | |||
return max($rowList); | |||
} | |||
/** | |||
* Generate a unique ID for cache referencing | |||
* | |||
* @return string Unique Reference | |||
*/ | |||
protected function getUniqueID() | |||
{ | |||
if (function_exists('posix_getpid')) { | |||
$baseUnique = posix_getpid(); | |||
} else { | |||
$baseUnique = mt_rand(); | |||
} | |||
return uniqid($baseUnique, true); | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
$this->currentCellIsDirty; | |||
$this->storeData(); | |||
$this->parent = $parent; | |||
if (($this->currentObject !== null) && (is_object($this->currentObject))) { | |||
$this->currentObject->attach($this); | |||
} | |||
} // function copyCellCollection() | |||
/** | |||
* Remove a row, deleting all cells in that row | |||
* | |||
* @param string $row Row number to remove | |||
* @return void | |||
*/ | |||
public function removeRow($row) | |||
{ | |||
foreach ($this->getCellList() as $coord) { | |||
sscanf($coord, '%[A-Z]%d', $c, $r); | |||
if ($r == $row) { | |||
$this->deleteCacheData($coord); | |||
} | |||
} | |||
} | |||
/** | |||
* Remove a column, deleting all cells in that column | |||
* | |||
* @param string $column Column ID to remove | |||
* @return void | |||
*/ | |||
public function removeColumn($column) | |||
{ | |||
foreach ($this->getCellList() as $coord) { | |||
sscanf($coord, '%[A-Z]%d', $c, $r); | |||
if ($c == $column) { | |||
$this->deleteCacheData($coord); | |||
} | |||
} | |||
} | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
return true; | |||
} | |||
} |
@ -0,0 +1,208 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_DiscISAM | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Name of the file for this cache | |||
* | |||
* @var string | |||
*/ | |||
private $fileName = null; | |||
/** | |||
* File handle for this cache file | |||
* | |||
* @var resource | |||
*/ | |||
private $fileHandle = null; | |||
/** | |||
* Directory/Folder where the cache file is located | |||
* | |||
* @var string | |||
*/ | |||
private $cacheDirectory = null; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
fseek($this->fileHandle, 0, SEEK_END); | |||
$this->cellCache[$this->currentObjectID] = array( | |||
'ptr' => ftell($this->fileHandle), | |||
'sz' => fwrite($this->fileHandle, serialize($this->currentObject)) | |||
); | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (!isset($this->cellCache[$pCoord])) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
fseek($this->fileHandle, $this->cellCache[$pCoord]['ptr']); | |||
$this->currentObject = unserialize(fread($this->fileHandle, $this->cellCache[$pCoord]['sz'])); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::copyCellCollection($parent); | |||
// Get a new id for the new file name | |||
$baseUnique = $this->getUniqueID(); | |||
$newFileName = $this->cacheDirectory.'/PHPExcel.'.$baseUnique.'.cache'; | |||
// Copy the existing cell cache file | |||
copy($this->fileName, $newFileName); | |||
$this->fileName = $newFileName; | |||
// Open the copied cell cache file | |||
$this->fileHandle = fopen($this->fileName, 'a+'); | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
// Close down the temporary cache file | |||
$this->__destruct(); | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
* @param array of mixed $arguments Additional initialisation arguments | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent, $arguments) | |||
{ | |||
$this->cacheDirectory = ((isset($arguments['dir'])) && ($arguments['dir'] !== null)) | |||
? $arguments['dir'] | |||
: PHPExcel_Shared_File::sys_get_temp_dir(); | |||
parent::__construct($parent); | |||
if (is_null($this->fileHandle)) { | |||
$baseUnique = $this->getUniqueID(); | |||
$this->fileName = $this->cacheDirectory.'/PHPExcel.'.$baseUnique.'.cache'; | |||
$this->fileHandle = fopen($this->fileName, 'a+'); | |||
} | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
if (!is_null($this->fileHandle)) { | |||
fclose($this->fileHandle); | |||
unlink($this->fileName); | |||
} | |||
$this->fileHandle = null; | |||
} | |||
} |
@ -0,0 +1,103 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_ICache | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
interface PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell); | |||
/** | |||
* Add or Update a cell in cache | |||
* | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function updateCacheData(PHPExcel_Cell $cell); | |||
/** | |||
* Fetch a cell from cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to retrieve | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function getCacheData($pCoord); | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord); | |||
/** | |||
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? | |||
* | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord); | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList(); | |||
/** | |||
* Get the list of all cell addresses currently held in cache sorted by column and row | |||
* | |||
* @return string[] | |||
*/ | |||
public function getSortedCellList(); | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent); | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable(); | |||
} |
@ -0,0 +1,149 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_Igbinary | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
$this->cellCache[$this->currentObjectID] = igbinary_serialize($this->currentObject); | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} // function _storeData() | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} // function addCacheData() | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (!isset($this->cellCache[$pCoord])) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = igbinary_unserialize($this->cellCache[$pCoord]); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} // function getCacheData() | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} // function unsetWorksheetCells() | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
if (!function_exists('igbinary_serialize')) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@ -0,0 +1,308 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_Memcache | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Prefix used to uniquely identify cache data for this worksheet | |||
* | |||
* @var string | |||
*/ | |||
private $cachePrefix = null; | |||
/** | |||
* Cache timeout | |||
* | |||
* @var integer | |||
*/ | |||
private $cacheTime = 600; | |||
/** | |||
* Memcache interface | |||
* | |||
* @var resource | |||
*/ | |||
private $memcache = null; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
$obj = serialize($this->currentObject); | |||
if (!$this->memcache->replace($this->cachePrefix . $this->currentObjectID . '.cache', $obj, null, $this->cacheTime)) { | |||
if (!$this->memcache->add($this->cachePrefix . $this->currentObjectID . '.cache', $obj, null, $this->cacheTime)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception("Failed to store cell {$this->currentObjectID} in MemCache"); | |||
} | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} // function _storeData() | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->cellCache[$pCoord] = true; | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} // function addCacheData() | |||
/** | |||
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? | |||
* | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @return boolean | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord) | |||
{ | |||
// Check if the requested entry is the current object, or exists in the cache | |||
if (parent::isDataSet($pCoord)) { | |||
if ($this->currentObjectID == $pCoord) { | |||
return true; | |||
} | |||
// Check if the requested entry still exists in Memcache | |||
$success = $this->memcache->get($this->cachePrefix.$pCoord.'.cache'); | |||
if ($success === false) { | |||
// Entry no longer exists in Memcache, so clear it from the cache array | |||
parent::deleteCacheData($pCoord); | |||
throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); | |||
} | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (parent::isDataSet($pCoord)) { | |||
$obj = $this->memcache->get($this->cachePrefix . $pCoord . '.cache'); | |||
if ($obj === false) { | |||
// Entry no longer exists in Memcache, so clear it from the cache array | |||
parent::deleteCacheData($pCoord); | |||
throw new PHPExcel_Exception("Cell entry {$pCoord} no longer exists in MemCache"); | |||
} | |||
} else { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = unserialize($obj); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord) | |||
{ | |||
// Delete the entry from Memcache | |||
$this->memcache->delete($this->cachePrefix . $pCoord . '.cache'); | |||
// Delete the entry from our cell address array | |||
parent::deleteCacheData($pCoord); | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::copyCellCollection($parent); | |||
// Get a new id for the new file name | |||
$baseUnique = $this->getUniqueID(); | |||
$newCachePrefix = substr(md5($baseUnique), 0, 8) . '.'; | |||
$cacheList = $this->getCellList(); | |||
foreach ($cacheList as $cellID) { | |||
if ($cellID != $this->currentObjectID) { | |||
$obj = $this->memcache->get($this->cachePrefix.$cellID.'.cache'); | |||
if ($obj === false) { | |||
// Entry no longer exists in Memcache, so clear it from the cache array | |||
parent::deleteCacheData($cellID); | |||
throw new PHPExcel_Exception("Cell entry {$cellID} no longer exists in MemCache"); | |||
} | |||
if (!$this->memcache->add($newCachePrefix . $cellID . '.cache', $obj, null, $this->cacheTime)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception("Failed to store cell {$cellID} in MemCache"); | |||
} | |||
} | |||
} | |||
$this->cachePrefix = $newCachePrefix; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
// Flush the Memcache cache | |||
$this->__destruct(); | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
* @param array of mixed $arguments Additional initialisation arguments | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent, $arguments) | |||
{ | |||
$memcacheServer = (isset($arguments['memcacheServer'])) ? $arguments['memcacheServer'] : 'localhost'; | |||
$memcachePort = (isset($arguments['memcachePort'])) ? $arguments['memcachePort'] : 11211; | |||
$cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; | |||
if (is_null($this->cachePrefix)) { | |||
$baseUnique = $this->getUniqueID(); | |||
$this->cachePrefix = substr(md5($baseUnique), 0, 8) . '.'; | |||
// Set a new Memcache object and connect to the Memcache server | |||
$this->memcache = new Memcache(); | |||
if (!$this->memcache->addServer($memcacheServer, $memcachePort, false, 50, 5, 5, true, array($this, 'failureCallback'))) { | |||
throw new PHPExcel_Exception("Could not connect to MemCache server at {$memcacheServer}:{$memcachePort}"); | |||
} | |||
$this->cacheTime = $cacheTime; | |||
parent::__construct($parent); | |||
} | |||
} | |||
/** | |||
* Memcache error handler | |||
* | |||
* @param string $host Memcache server | |||
* @param integer $port Memcache port | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function failureCallback($host, $port) | |||
{ | |||
throw new PHPExcel_Exception("memcache {$host}:{$port} failed"); | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
$cacheList = $this->getCellList(); | |||
foreach ($cacheList as $cellID) { | |||
$this->memcache->delete($this->cachePrefix.$cellID . '.cache'); | |||
} | |||
} | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
if (!function_exists('memcache_add')) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@ -0,0 +1,118 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_Memory | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Dummy method callable from CacheBase, but unused by Memory cache | |||
* | |||
* @return void | |||
*/ | |||
protected function storeData() | |||
{ | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @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; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
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]; | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::copyCellCollection($parent); | |||
$newCollection = array(); | |||
foreach ($this->cellCache as $k => &$cell) { | |||
$newCollection[$k] = clone $cell; | |||
$newCollection[$k]->attach($this); | |||
} | |||
$this->cellCache = $newCollection; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
// Because cells are all stored as intact objects in memory, we need to detach each one from the parent | |||
foreach ($this->cellCache as $k => &$cell) { | |||
$cell->detach(); | |||
$this->cellCache[$k] = null; | |||
} | |||
unset($cell); | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} | |||
} |
@ -0,0 +1,133 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_MemoryGZip | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
$this->cellCache[$this->currentObjectID] = gzdeflate(serialize($this->currentObject)); | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (!isset($this->cellCache[$pCoord])) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = unserialize(gzinflate($this->cellCache[$pCoord])); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} | |||
} |
@ -0,0 +1,129 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_MemorySerialized | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
$this->cellCache[$this->currentObjectID] = serialize($this->currentObject); | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (!isset($this->cellCache[$pCoord])) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = unserialize($this->cellCache[$pCoord]); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} | |||
} |
@ -0,0 +1,200 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_PHPTemp | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Name of the file for this cache | |||
* | |||
* @var string | |||
*/ | |||
private $fileHandle = null; | |||
/** | |||
* Memory limit to use before reverting to file cache | |||
* | |||
* @var integer | |||
*/ | |||
private $memoryCacheSize = null; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
fseek($this->fileHandle, 0, SEEK_END); | |||
$this->cellCache[$this->currentObjectID] = array( | |||
'ptr' => ftell($this->fileHandle), | |||
'sz' => fwrite($this->fileHandle, serialize($this->currentObject)) | |||
); | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
if (!isset($this->cellCache[$pCoord])) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
fseek($this->fileHandle, $this->cellCache[$pCoord]['ptr']); | |||
$this->currentObject = unserialize(fread($this->fileHandle, $this->cellCache[$pCoord]['sz'])); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::copyCellCollection($parent); | |||
// Open a new stream for the cell cache data | |||
$newFileHandle = fopen('php://temp/maxmemory:' . $this->memoryCacheSize, 'a+'); | |||
// Copy the existing cell cache data to the new stream | |||
fseek($this->fileHandle, 0); | |||
while (!feof($this->fileHandle)) { | |||
fwrite($newFileHandle, fread($this->fileHandle, 1024)); | |||
} | |||
$this->fileHandle = $newFileHandle; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
// Close down the php://temp file | |||
$this->__destruct(); | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
* @param array of mixed $arguments Additional initialisation arguments | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent, $arguments) | |||
{ | |||
$this->memoryCacheSize = (isset($arguments['memoryCacheSize'])) ? $arguments['memoryCacheSize'] : '1MB'; | |||
parent::__construct($parent); | |||
if (is_null($this->fileHandle)) { | |||
$this->fileHandle = fopen('php://temp/maxmemory:' . $this->memoryCacheSize, 'a+'); | |||
} | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
if (!is_null($this->fileHandle)) { | |||
fclose($this->fileHandle); | |||
} | |||
$this->fileHandle = null; | |||
} | |||
} |
@ -0,0 +1,307 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_SQLite | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Database table name | |||
* | |||
* @var string | |||
*/ | |||
private $TableName = null; | |||
/** | |||
* Database handle | |||
* | |||
* @var resource | |||
*/ | |||
private $DBHandle = null; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
if (!$this->DBHandle->queryExec("INSERT OR REPLACE INTO kvp_".$this->TableName." VALUES('".$this->currentObjectID."','".sqlite_escape_string(serialize($this->currentObject))."')")) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
$query = "SELECT value FROM kvp_".$this->TableName." WHERE id='".$pCoord."'"; | |||
$cellResultSet = $this->DBHandle->query($query, SQLITE_ASSOC); | |||
if ($cellResultSet === false) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} elseif ($cellResultSet->numRows() == 0) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$cellResult = $cellResultSet->fetchSingle(); | |||
$this->currentObject = unserialize($cellResult); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Is a value set for an indexed cell? | |||
* | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return true; | |||
} | |||
// Check if the requested entry exists in the cache | |||
$query = "SELECT id FROM kvp_".$this->TableName." WHERE id='".$pCoord."'"; | |||
$cellResultSet = $this->DBHandle->query($query, SQLITE_ASSOC); | |||
if ($cellResultSet === false) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} elseif ($cellResultSet->numRows() == 0) { | |||
// Return null if requested entry doesn't exist in cache | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
$this->currentObject->detach(); | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
// Check if the requested entry exists in the cache | |||
$query = "DELETE FROM kvp_".$this->TableName." WHERE id='".$pCoord."'"; | |||
if (!$this->DBHandle->queryExec($query)) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
/** | |||
* 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; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
$query = "SELECT id FROM kvp_".$this->TableName; | |||
$cellIdsResult = $this->DBHandle->unbufferedQuery($query, SQLITE_ASSOC); | |||
if ($cellIdsResult === false) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} | |||
$cellKeys = array(); | |||
foreach ($cellIdsResult as $row) { | |||
$cellKeys[] = $row['id']; | |||
} | |||
return $cellKeys; | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
$this->currentCellIsDirty; | |||
$this->storeData(); | |||
// Get a new id for the new table name | |||
$tableName = str_replace('.', '_', $this->getUniqueID()); | |||
if (!$this->DBHandle->queryExec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB) | |||
AS SELECT * FROM kvp_'.$this->TableName) | |||
) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} | |||
// Copy the existing cell cache file | |||
$this->TableName = $tableName; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
// Close down the temporary cache file | |||
$this->__destruct(); | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::__construct($parent); | |||
if (is_null($this->DBHandle)) { | |||
$this->TableName = str_replace('.', '_', $this->getUniqueID()); | |||
$_DBName = ':memory:'; | |||
$this->DBHandle = new SQLiteDatabase($_DBName); | |||
if ($this->DBHandle === false) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} | |||
if (!$this->DBHandle->queryExec('CREATE TABLE kvp_'.$this->TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) { | |||
throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError())); | |||
} | |||
} | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
if (!is_null($this->DBHandle)) { | |||
$this->DBHandle->queryExec('DROP TABLE kvp_'.$this->TableName); | |||
} | |||
$this->DBHandle = null; | |||
} | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
if (!function_exists('sqlite_open')) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@ -0,0 +1,346 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_SQLite3 | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Database table name | |||
* | |||
* @var string | |||
*/ | |||
private $TableName = null; | |||
/** | |||
* Database handle | |||
* | |||
* @var resource | |||
*/ | |||
private $DBHandle = null; | |||
/** | |||
* Prepared statement for a SQLite3 select query | |||
* | |||
* @var SQLite3Stmt | |||
*/ | |||
private $selectQuery; | |||
/** | |||
* Prepared statement for a SQLite3 insert query | |||
* | |||
* @var SQLite3Stmt | |||
*/ | |||
private $insertQuery; | |||
/** | |||
* Prepared statement for a SQLite3 update query | |||
* | |||
* @var SQLite3Stmt | |||
*/ | |||
private $updateQuery; | |||
/** | |||
* Prepared statement for a SQLite3 delete query | |||
* | |||
* @var SQLite3Stmt | |||
*/ | |||
private $deleteQuery; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
$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; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
$this->selectQuery->bindValue('id', $pCoord, SQLITE3_TEXT); | |||
$cellResult = $this->selectQuery->execute(); | |||
if ($cellResult === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
$cellData = $cellResult->fetchArray(SQLITE3_ASSOC); | |||
if ($cellData === false) { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = unserialize($cellData['value']); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Is a value set for an indexed cell? | |||
* | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return true; | |||
} | |||
// Check if the requested entry exists in the cache | |||
$this->selectQuery->bindValue('id', $pCoord, SQLITE3_TEXT); | |||
$cellResult = $this->selectQuery->execute(); | |||
if ($cellResult === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
$cellData = $cellResult->fetchArray(SQLITE3_ASSOC); | |||
return ($cellData === false) ? false : true; | |||
} | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
$this->currentObject->detach(); | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
// Check if the requested entry exists in the cache | |||
$this->deleteQuery->bindValue('id', $pCoord, SQLITE3_TEXT); | |||
$result = $this->deleteQuery->execute(); | |||
if ($result === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
/** | |||
* Move a cell object from one address to another | |||
* | |||
* @param string $fromAddress Current address of the cell to move | |||
* @param string $toAddress Destination address of the cell to move | |||
* @return boolean | |||
*/ | |||
public function moveCell($fromAddress, $toAddress) | |||
{ | |||
if ($fromAddress === $this->currentObjectID) { | |||
$this->currentObjectID = $toAddress; | |||
} | |||
$this->deleteQuery->bindValue('id', $toAddress, SQLITE3_TEXT); | |||
$result = $this->deleteQuery->execute(); | |||
if ($result === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
$this->updateQuery->bindValue('toid', $toAddress, SQLITE3_TEXT); | |||
$this->updateQuery->bindValue('fromid', $fromAddress, SQLITE3_TEXT); | |||
$result = $this->updateQuery->execute(); | |||
if ($result === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
return true; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
$query = "SELECT id FROM kvp_".$this->TableName; | |||
$cellIdsResult = $this->DBHandle->query($query); | |||
if ($cellIdsResult === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
$cellKeys = array(); | |||
while ($row = $cellIdsResult->fetchArray(SQLITE3_ASSOC)) { | |||
$cellKeys[] = $row['id']; | |||
} | |||
return $cellKeys; | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
$this->currentCellIsDirty; | |||
$this->storeData(); | |||
// Get a new id for the new table name | |||
$tableName = str_replace('.', '_', $this->getUniqueID()); | |||
if (!$this->DBHandle->exec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB) | |||
AS SELECT * FROM kvp_'.$this->TableName) | |||
) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
// Copy the existing cell cache file | |||
$this->TableName = $tableName; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
// Close down the temporary cache file | |||
$this->__destruct(); | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::__construct($parent); | |||
if (is_null($this->DBHandle)) { | |||
$this->TableName = str_replace('.', '_', $this->getUniqueID()); | |||
$_DBName = ':memory:'; | |||
$this->DBHandle = new SQLite3($_DBName); | |||
if ($this->DBHandle === false) { | |||
throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg()); | |||
} | |||
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"); | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
if (!is_null($this->DBHandle)) { | |||
$this->DBHandle->exec('DROP TABLE kvp_'.$this->TableName); | |||
$this->DBHandle->close(); | |||
} | |||
$this->DBHandle = null; | |||
} | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
if (!class_exists('SQLite3', false)) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@ -0,0 +1,289 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorage_Wincache | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache | |||
{ | |||
/** | |||
* Prefix used to uniquely identify cache data for this worksheet | |||
* | |||
* @var string | |||
*/ | |||
private $cachePrefix = null; | |||
/** | |||
* Cache timeout | |||
* | |||
* @var integer | |||
*/ | |||
private $cacheTime = 600; | |||
/** | |||
* Store cell data in cache for the current cell object if it's "dirty", | |||
* and the 'nullify' the current cell object | |||
* | |||
* @return void | |||
* @throws PHPExcel_Exception | |||
*/ | |||
protected function storeData() | |||
{ | |||
if ($this->currentCellIsDirty && !empty($this->currentObjectID)) { | |||
$this->currentObject->detach(); | |||
$obj = serialize($this->currentObject); | |||
if (wincache_ucache_exists($this->cachePrefix.$this->currentObjectID.'.cache')) { | |||
if (!wincache_ucache_set($this->cachePrefix.$this->currentObjectID.'.cache', $obj, $this->cacheTime)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception('Failed to store cell '.$this->currentObjectID.' in WinCache'); | |||
} | |||
} else { | |||
if (!wincache_ucache_add($this->cachePrefix.$this->currentObjectID.'.cache', $obj, $this->cacheTime)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception('Failed to store cell '.$this->currentObjectID.' in WinCache'); | |||
} | |||
} | |||
$this->currentCellIsDirty = false; | |||
} | |||
$this->currentObjectID = $this->currentObject = null; | |||
} | |||
/** | |||
* Add or Update a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to update | |||
* @param PHPExcel_Cell $cell Cell to update | |||
* @return PHPExcel_Cell | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addCacheData($pCoord, PHPExcel_Cell $cell) | |||
{ | |||
if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) { | |||
$this->storeData(); | |||
} | |||
$this->cellCache[$pCoord] = true; | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = $cell; | |||
$this->currentCellIsDirty = true; | |||
return $cell; | |||
} | |||
/** | |||
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? | |||
* | |||
* @param string $pCoord Coordinate address of the cell to check | |||
* @return boolean | |||
*/ | |||
public function isDataSet($pCoord) | |||
{ | |||
// Check if the requested entry is the current object, or exists in the cache | |||
if (parent::isDataSet($pCoord)) { | |||
if ($this->currentObjectID == $pCoord) { | |||
return true; | |||
} | |||
// Check if the requested entry still exists in cache | |||
$success = wincache_ucache_exists($this->cachePrefix.$pCoord.'.cache'); | |||
if ($success === false) { | |||
// Entry no longer exists in Wincache, so clear it from the cache array | |||
parent::deleteCacheData($pCoord); | |||
throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); | |||
} | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get cell at a specific coordinate | |||
* | |||
* @param string $pCoord Coordinate of the cell | |||
* @throws PHPExcel_Exception | |||
* @return PHPExcel_Cell Cell that was found, or null if not found | |||
*/ | |||
public function getCacheData($pCoord) | |||
{ | |||
if ($pCoord === $this->currentObjectID) { | |||
return $this->currentObject; | |||
} | |||
$this->storeData(); | |||
// Check if the entry that has been requested actually exists | |||
$obj = null; | |||
if (parent::isDataSet($pCoord)) { | |||
$success = false; | |||
$obj = wincache_ucache_get($this->cachePrefix.$pCoord.'.cache', $success); | |||
if ($success === false) { | |||
// Entry no longer exists in WinCache, so clear it from the cache array | |||
parent::deleteCacheData($pCoord); | |||
throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); | |||
} | |||
} else { | |||
// Return null if requested entry doesn't exist in cache | |||
return null; | |||
} | |||
// Set current entry to the requested entry | |||
$this->currentObjectID = $pCoord; | |||
$this->currentObject = unserialize($obj); | |||
// Re-attach this as the cell's parent | |||
$this->currentObject->attach($this); | |||
// Return requested entry | |||
return $this->currentObject; | |||
} | |||
/** | |||
* Get a list of all cell addresses currently held in cache | |||
* | |||
* @return string[] | |||
*/ | |||
public function getCellList() | |||
{ | |||
if ($this->currentObjectID !== null) { | |||
$this->storeData(); | |||
} | |||
return parent::getCellList(); | |||
} | |||
/** | |||
* Delete a cell in cache identified by coordinate address | |||
* | |||
* @param string $pCoord Coordinate address of the cell to delete | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function deleteCacheData($pCoord) | |||
{ | |||
// Delete the entry from Wincache | |||
wincache_ucache_delete($this->cachePrefix.$pCoord.'.cache'); | |||
// Delete the entry from our cell address array | |||
parent::deleteCacheData($pCoord); | |||
} | |||
/** | |||
* Clone the cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The new worksheet | |||
* @return void | |||
*/ | |||
public function copyCellCollection(PHPExcel_Worksheet $parent) | |||
{ | |||
parent::copyCellCollection($parent); | |||
// Get a new id for the new file name | |||
$baseUnique = $this->getUniqueID(); | |||
$newCachePrefix = substr(md5($baseUnique), 0, 8) . '.'; | |||
$cacheList = $this->getCellList(); | |||
foreach ($cacheList as $cellID) { | |||
if ($cellID != $this->currentObjectID) { | |||
$success = false; | |||
$obj = wincache_ucache_get($this->cachePrefix.$cellID.'.cache', $success); | |||
if ($success === false) { | |||
// Entry no longer exists in WinCache, so clear it from the cache array | |||
parent::deleteCacheData($cellID); | |||
throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in Wincache'); | |||
} | |||
if (!wincache_ucache_add($newCachePrefix.$cellID.'.cache', $obj, $this->cacheTime)) { | |||
$this->__destruct(); | |||
throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in Wincache'); | |||
} | |||
} | |||
} | |||
$this->cachePrefix = $newCachePrefix; | |||
} | |||
/** | |||
* Clear the cell collection and disconnect from our parent | |||
* | |||
* @return void | |||
*/ | |||
public function unsetWorksheetCells() | |||
{ | |||
if (!is_null($this->currentObject)) { | |||
$this->currentObject->detach(); | |||
$this->currentObject = $this->currentObjectID = null; | |||
} | |||
// Flush the WinCache cache | |||
$this->__destruct(); | |||
$this->cellCache = array(); | |||
// detach ourself from the worksheet, so that it can then delete this object successfully | |||
$this->parent = null; | |||
} | |||
/** | |||
* Initialise this new cell collection | |||
* | |||
* @param PHPExcel_Worksheet $parent The worksheet for this cell collection | |||
* @param array of mixed $arguments Additional initialisation arguments | |||
*/ | |||
public function __construct(PHPExcel_Worksheet $parent, $arguments) | |||
{ | |||
$cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; | |||
if (is_null($this->cachePrefix)) { | |||
$baseUnique = $this->getUniqueID(); | |||
$this->cachePrefix = substr(md5($baseUnique), 0, 8).'.'; | |||
$this->cacheTime = $cacheTime; | |||
parent::__construct($parent); | |||
} | |||
} | |||
/** | |||
* Destroy this cell collection | |||
*/ | |||
public function __destruct() | |||
{ | |||
$cacheList = $this->getCellList(); | |||
foreach ($cacheList as $cellID) { | |||
wincache_ucache_delete($this->cachePrefix.$cellID.'.cache'); | |||
} | |||
} | |||
/** | |||
* Identify whether the caching method is currently available | |||
* Some methods are dependent on the availability of certain extensions being enabled in the PHP build | |||
* | |||
* @return boolean | |||
*/ | |||
public static function cacheMethodIsAvailable() | |||
{ | |||
if (!function_exists('wincache_ucache_add')) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@ -0,0 +1,231 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CachedObjectStorageFactory | |||
* | |||
* Copyright (c) 2006 - 2015 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_CachedObjectStorage | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CachedObjectStorageFactory | |||
{ | |||
const cache_in_memory = 'Memory'; | |||
const cache_in_memory_gzip = 'MemoryGZip'; | |||
const cache_in_memory_serialized = 'MemorySerialized'; | |||
const cache_igbinary = 'Igbinary'; | |||
const cache_to_discISAM = 'DiscISAM'; | |||
const cache_to_apc = 'APC'; | |||
const cache_to_memcache = 'Memcache'; | |||
const cache_to_phpTemp = 'PHPTemp'; | |||
const cache_to_wincache = 'Wincache'; | |||
const cache_to_sqlite = 'SQLite'; | |||
const cache_to_sqlite3 = 'SQLite3'; | |||
/** | |||
* Name of the method used for cell cacheing | |||
* | |||
* @var string | |||
*/ | |||
private static $cacheStorageMethod = null; | |||
/** | |||
* Name of the class used for cell cacheing | |||
* | |||
* @var string | |||
*/ | |||
private static $cacheStorageClass = null; | |||
/** | |||
* List of all possible cache storage methods | |||
* | |||
* @var string[] | |||
*/ | |||
private static $storageMethods = array( | |||
self::cache_in_memory, | |||
self::cache_in_memory_gzip, | |||
self::cache_in_memory_serialized, | |||
self::cache_igbinary, | |||
self::cache_to_phpTemp, | |||
self::cache_to_discISAM, | |||
self::cache_to_apc, | |||
self::cache_to_memcache, | |||
self::cache_to_wincache, | |||
self::cache_to_sqlite, | |||
self::cache_to_sqlite3, | |||
); | |||
/** | |||
* Default arguments for each cache storage method | |||
* | |||
* @var array of mixed array | |||
*/ | |||
private static $storageMethodDefaultParameters = array( | |||
self::cache_in_memory => array( | |||
), | |||
self::cache_in_memory_gzip => array( | |||
), | |||
self::cache_in_memory_serialized => array( | |||
), | |||
self::cache_igbinary => array( | |||
), | |||
self::cache_to_phpTemp => array( 'memoryCacheSize' => '1MB' | |||
), | |||
self::cache_to_discISAM => array( 'dir' => null | |||
), | |||
self::cache_to_apc => array( 'cacheTime' => 600 | |||
), | |||
self::cache_to_memcache => array( 'memcacheServer' => 'localhost', | |||
'memcachePort' => 11211, | |||
'cacheTime' => 600 | |||
), | |||
self::cache_to_wincache => array( 'cacheTime' => 600 | |||
), | |||
self::cache_to_sqlite => array( | |||
), | |||
self::cache_to_sqlite3 => array( | |||
), | |||
); | |||
/** | |||
* Arguments for the active cache storage method | |||
* | |||
* @var array of mixed array | |||
*/ | |||
private static $storageMethodParameters = array(); | |||
/** | |||
* Return the current cache storage method | |||
* | |||
* @return string|null | |||
**/ | |||
public static function getCacheStorageMethod() | |||
{ | |||
return self::$cacheStorageMethod; | |||
} | |||
/** | |||
* Return the current cache storage class | |||
* | |||
* @return PHPExcel_CachedObjectStorage_ICache|null | |||
**/ | |||
public static function getCacheStorageClass() | |||
{ | |||
return self::$cacheStorageClass; | |||
} | |||
/** | |||
* Return the list of all possible cache storage methods | |||
* | |||
* @return string[] | |||
**/ | |||
public static function getAllCacheStorageMethods() | |||
{ | |||
return self::$storageMethods; | |||
} | |||
/** | |||
* Return the list of all available cache storage methods | |||
* | |||
* @return string[] | |||
**/ | |||
public static function getCacheStorageMethods() | |||
{ | |||
$activeMethods = array(); | |||
foreach (self::$storageMethods as $storageMethod) { | |||
$cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $storageMethod; | |||
if (call_user_func(array($cacheStorageClass, 'cacheMethodIsAvailable'))) { | |||
$activeMethods[] = $storageMethod; | |||
} | |||
} | |||
return $activeMethods; | |||
} | |||
/** | |||
* Identify the cache storage method to use | |||
* | |||
* @param string $method Name of the method to use for cell cacheing | |||
* @param array of mixed $arguments Additional arguments to pass to the cell caching class | |||
* when instantiating | |||
* @return boolean | |||
**/ | |||
public static function initialize($method = self::cache_in_memory, $arguments = array()) | |||
{ | |||
if (!in_array($method, self::$storageMethods)) { | |||
return false; | |||
} | |||
$cacheStorageClass = 'PHPExcel_CachedObjectStorage_'.$method; | |||
if (!call_user_func(array( $cacheStorageClass, | |||
'cacheMethodIsAvailable'))) { | |||
return false; | |||
} | |||
self::$storageMethodParameters[$method] = self::$storageMethodDefaultParameters[$method]; | |||
foreach ($arguments as $k => $v) { | |||
if (array_key_exists($k, self::$storageMethodParameters[$method])) { | |||
self::$storageMethodParameters[$method][$k] = $v; | |||
} | |||
} | |||
if (self::$cacheStorageMethod === null) { | |||
self::$cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $method; | |||
self::$cacheStorageMethod = $method; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Initialise the cache storage | |||
* | |||
* @param PHPExcel_Worksheet $parent Enable cell caching for this worksheet | |||
* @return PHPExcel_CachedObjectStorage_ICache | |||
**/ | |||
public static function getInstance(PHPExcel_Worksheet $parent) | |||
{ | |||
$cacheMethodIsAvailable = true; | |||
if (self::$cacheStorageMethod === null) { | |||
$cacheMethodIsAvailable = self::initialize(); | |||
} | |||
if ($cacheMethodIsAvailable) { | |||
$instance = new self::$cacheStorageClass( | |||
$parent, | |||
self::$storageMethodParameters[self::$cacheStorageMethod] | |||
); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* Clear the cache storage | |||
* | |||
**/ | |||
public static function finalize() | |||
{ | |||
self::$cacheStorageMethod = null; | |||
self::$cacheStorageClass = null; | |||
self::$storageMethodParameters = array(); | |||
} | |||
} |
@ -0,0 +1,94 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CalcEngine_CyclicReferenceStack | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CalcEngine_CyclicReferenceStack | |||
{ | |||
/** | |||
* The call stack for calculated cells | |||
* | |||
* @var mixed[] | |||
*/ | |||
private $stack = array(); | |||
/** | |||
* Return the number of entries on the stack | |||
* | |||
* @return integer | |||
*/ | |||
public function count() | |||
{ | |||
return count($this->stack); | |||
} | |||
/** | |||
* Push a new entry onto the stack | |||
* | |||
* @param mixed $value | |||
*/ | |||
public function push($value) | |||
{ | |||
$this->stack[$value] = $value; | |||
} | |||
/** | |||
* Pop the last entry from the stack | |||
* | |||
* @return mixed | |||
*/ | |||
public function pop() | |||
{ | |||
return array_pop($this->stack); | |||
} | |||
/** | |||
* Test to see if a specified entry exists on the stack | |||
* | |||
* @param mixed $value The value to test | |||
*/ | |||
public function onStack($value) | |||
{ | |||
return isset($this->stack[$value]); | |||
} | |||
/** | |||
* Clear the stack | |||
*/ | |||
public function clear() | |||
{ | |||
$this->stack = array(); | |||
} | |||
/** | |||
* Return an array of all entries on the stack | |||
* | |||
* @return mixed[] | |||
*/ | |||
public function showStack() | |||
{ | |||
return $this->stack; | |||
} | |||
} |
@ -0,0 +1,151 @@ | |||
<?php | |||
/** | |||
* PHPExcel_CalcEngine_Logger | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_CalcEngine_Logger | |||
{ | |||
/** | |||
* 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 | |||
* | |||
* @var boolean | |||
*/ | |||
private $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 | |||
* | |||
* @var boolean | |||
*/ | |||
private $echoDebugLog = false; | |||
/** | |||
* The debug log generated by the calculation engine | |||
* | |||
* @var string[] | |||
*/ | |||
private $debugLog = array(); | |||
/** | |||
* The calculation engine cell reference stack | |||
* | |||
* @var PHPExcel_CalcEngine_CyclicReferenceStack | |||
*/ | |||
private $cellStack; | |||
/** | |||
* Instantiate a Calculation engine logger | |||
* | |||
* @param PHPExcel_CalcEngine_CyclicReferenceStack $stack | |||
*/ | |||
public function __construct(PHPExcel_CalcEngine_CyclicReferenceStack $stack) | |||
{ | |||
$this->cellStack = $stack; | |||
} | |||
/** | |||
* Enable/Disable Calculation engine logging | |||
* | |||
* @param boolean $pValue | |||
*/ | |||
public function setWriteDebugLog($pValue = false) | |||
{ | |||
$this->writeDebugLog = $pValue; | |||
} | |||
/** | |||
* Return whether calculation engine logging is enabled or disabled | |||
* | |||
* @return boolean | |||
*/ | |||
public function getWriteDebugLog() | |||
{ | |||
return $this->writeDebugLog; | |||
} | |||
/** | |||
* Enable/Disable echoing of debug log information | |||
* | |||
* @param boolean $pValue | |||
*/ | |||
public function setEchoDebugLog($pValue = false) | |||
{ | |||
$this->echoDebugLog = $pValue; | |||
} | |||
/** | |||
* Return whether echoing of debug log information is enabled or disabled | |||
* | |||
* @return boolean | |||
*/ | |||
public function getEchoDebugLog() | |||
{ | |||
return $this->echoDebugLog; | |||
} | |||
/** | |||
* Write an entry to the calculation engine debug log | |||
*/ | |||
public function writeDebugLog() | |||
{ | |||
// Only write the debug log if logging is enabled | |||
if ($this->writeDebugLog) { | |||
$message = implode(func_get_args()); | |||
$cellReference = implode(' -> ', $this->cellStack->showStack()); | |||
if ($this->echoDebugLog) { | |||
echo $cellReference, | |||
($this->cellStack->count() > 0 ? ' => ' : ''), | |||
$message, | |||
PHP_EOL; | |||
} | |||
$this->debugLog[] = $cellReference . | |||
($this->cellStack->count() > 0 ? ' => ' : '') . | |||
$message; | |||
} | |||
} | |||
/** | |||
* Clear the calculation engine debug log | |||
*/ | |||
public function clearLog() | |||
{ | |||
$this->debugLog = array(); | |||
} | |||
/** | |||
* Return the calculation engine debug log | |||
* | |||
* @return string[] | |||
*/ | |||
public function getLog() | |||
{ | |||
return $this->debugLog; | |||
} | |||
} |
@ -0,0 +1,676 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Calculation_Database | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Database | |||
{ | |||
/** | |||
* fieldExtract | |||
* | |||
* Extracts the column ID to use for the data field. | |||
* | |||
* @access private | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param mixed $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @return string|NULL | |||
* | |||
*/ | |||
private static function fieldExtract($database, $field) | |||
{ | |||
$field = strtoupper(PHPExcel_Calculation_Functions::flattenSingleValue($field)); | |||
$fieldNames = array_map('strtoupper', array_shift($database)); | |||
if (is_numeric($field)) { | |||
$keys = array_keys($fieldNames); | |||
return $keys[$field-1]; | |||
} | |||
$key = array_search($field, $fieldNames); | |||
return ($key) ? $key : null; | |||
} | |||
/** | |||
* filter | |||
* | |||
* Parses the selection criteria, extracts the database rows that match those criteria, and | |||
* returns that subset of rows. | |||
* | |||
* @access private | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return array of mixed | |||
* | |||
*/ | |||
private static function filter($database, $criteria) | |||
{ | |||
$fieldNames = array_shift($database); | |||
$criteriaNames = array_shift($criteria); | |||
// Convert the criteria into a set of AND/OR conditions with [:placeholders] | |||
$testConditions = $testValues = array(); | |||
$testConditionsCount = 0; | |||
foreach ($criteriaNames as $key => $criteriaName) { | |||
$testCondition = array(); | |||
$testConditionCount = 0; | |||
foreach ($criteria as $row => $criterion) { | |||
if ($criterion[$key] > '') { | |||
$testCondition[] = '[:'.$criteriaName.']'.PHPExcel_Calculation_Functions::ifCondition($criterion[$key]); | |||
$testConditionCount++; | |||
} | |||
} | |||
if ($testConditionCount > 1) { | |||
$testConditions[] = 'OR(' . implode(',', $testCondition) . ')'; | |||
$testConditionsCount++; | |||
} elseif ($testConditionCount == 1) { | |||
$testConditions[] = $testCondition[0]; | |||
$testConditionsCount++; | |||
} | |||
} | |||
if ($testConditionsCount > 1) { | |||
$testConditionSet = 'AND(' . implode(',', $testConditions) . ')'; | |||
} elseif ($testConditionsCount == 1) { | |||
$testConditionSet = $testConditions[0]; | |||
} | |||
// Loop through each row of the database | |||
foreach ($database as $dataRow => $dataValues) { | |||
// Substitute actual values from the database row for our [:placeholders] | |||
$testConditionList = $testConditionSet; | |||
foreach ($criteriaNames as $key => $criteriaName) { | |||
$k = array_search($criteriaName, $fieldNames); | |||
if (isset($dataValues[$k])) { | |||
$dataValue = $dataValues[$k]; | |||
$dataValue = (is_string($dataValue)) ? PHPExcel_Calculation::wrapResult(strtoupper($dataValue)) : $dataValue; | |||
$testConditionList = str_replace('[:' . $criteriaName . ']', $dataValue, $testConditionList); | |||
} | |||
} | |||
// evaluate the criteria against the row data | |||
$result = PHPExcel_Calculation::getInstance()->_calculateFormulaValue('='.$testConditionList); | |||
// If the row failed to meet the criteria, remove it from the database | |||
if (!$result) { | |||
unset($database[$dataRow]); | |||
} | |||
} | |||
return $database; | |||
} | |||
private static function getFilteredColumn($database, $field, $criteria) | |||
{ | |||
// reduce the database to a set of rows that match all the criteria | |||
$database = self::filter($database, $criteria); | |||
// extract an array of values for the requested column | |||
$colData = array(); | |||
foreach ($database as $row) { | |||
$colData[] = $row[$field]; | |||
} | |||
return $colData; | |||
} | |||
/** | |||
* DAVERAGE | |||
* | |||
* Averages the values in a column of a list or database that match conditions you specify. | |||
* | |||
* Excel Function: | |||
* DAVERAGE(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DAVERAGE($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::AVERAGE( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DCOUNT | |||
* | |||
* Counts the cells that contain numbers in a column of a list or database that match conditions | |||
* that you specify. | |||
* | |||
* Excel Function: | |||
* DCOUNT(database,[field],criteria) | |||
* | |||
* Excel Function: | |||
* DAVERAGE(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return integer | |||
* | |||
* @TODO The field argument is optional. If field is omitted, DCOUNT counts all records in the | |||
* database that match the criteria. | |||
* | |||
*/ | |||
public static function DCOUNT($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::COUNT( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DCOUNTA | |||
* | |||
* Counts the nonblank cells in a column of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DCOUNTA(database,[field],criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return integer | |||
* | |||
* @TODO The field argument is optional. If field is omitted, DCOUNTA counts all records in the | |||
* database that match the criteria. | |||
* | |||
*/ | |||
public static function DCOUNTA($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// reduce the database to a set of rows that match all the criteria | |||
$database = self::filter($database, $criteria); | |||
// extract an array of values for the requested column | |||
$colData = array(); | |||
foreach ($database as $row) { | |||
$colData[] = $row[$field]; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::COUNTA( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DGET | |||
* | |||
* Extracts a single value from a column of a list or database that matches conditions that you | |||
* specify. | |||
* | |||
* Excel Function: | |||
* DGET(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return mixed | |||
* | |||
*/ | |||
public static function DGET($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
$colData = self::getFilteredColumn($database, $field, $criteria); | |||
if (count($colData) > 1) { | |||
return PHPExcel_Calculation_Functions::NaN(); | |||
} | |||
return $colData[0]; | |||
} | |||
/** | |||
* DMAX | |||
* | |||
* Returns the largest number in a column of a list or database that matches conditions you that | |||
* specify. | |||
* | |||
* Excel Function: | |||
* DMAX(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DMAX($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::MAX( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DMIN | |||
* | |||
* Returns the smallest number in a column of a list or database that matches conditions you that | |||
* specify. | |||
* | |||
* Excel Function: | |||
* DMIN(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DMIN($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::MIN( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DPRODUCT | |||
* | |||
* Multiplies the values in a column of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DPRODUCT(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DPRODUCT($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_MathTrig::PRODUCT( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DSTDEV | |||
* | |||
* Estimates the standard deviation of a population based on a sample by using the numbers in a | |||
* column of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DSTDEV(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DSTDEV($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::STDEV( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DSTDEVP | |||
* | |||
* Calculates the standard deviation of a population based on the entire population by using the | |||
* numbers in a column of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DSTDEVP(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DSTDEVP($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::STDEVP( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DSUM | |||
* | |||
* Adds the numbers in a column of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DSUM(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DSUM($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_MathTrig::SUM( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DVAR | |||
* | |||
* Estimates the variance of a population based on a sample by using the numbers in a column | |||
* of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DVAR(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DVAR($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::VARFunc( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
/** | |||
* DVARP | |||
* | |||
* Calculates the variance of a population based on the entire population by using the numbers | |||
* in a column of a list or database that match conditions that you specify. | |||
* | |||
* Excel Function: | |||
* DVARP(database,field,criteria) | |||
* | |||
* @access public | |||
* @category Database Functions | |||
* @param mixed[] $database The range of cells that makes up the list or database. | |||
* A database is a list of related data in which rows of related | |||
* information are records, and columns of data are fields. The | |||
* first row of the list contains labels for each column. | |||
* @param string|integer $field Indicates which column is used in the function. Enter the | |||
* column label enclosed between double quotation marks, such as | |||
* "Age" or "Yield," or a number (without quotation marks) that | |||
* represents the position of the column within the list: 1 for | |||
* the first column, 2 for the second column, and so on. | |||
* @param mixed[] $criteria The range of cells that contains the conditions you specify. | |||
* You can use any range for the criteria argument, as long as it | |||
* includes at least one column label and at least one cell below | |||
* the column label in which you specify a condition for the | |||
* column. | |||
* @return float | |||
* | |||
*/ | |||
public static function DVARP($database, $field, $criteria) | |||
{ | |||
$field = self::fieldExtract($database, $field); | |||
if (is_null($field)) { | |||
return null; | |||
} | |||
// Return | |||
return PHPExcel_Calculation_Statistical::VARP( | |||
self::getFilteredColumn($database, $field, $criteria) | |||
); | |||
} | |||
} |
@ -0,0 +1,46 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Calculation_Exception | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Exception extends PHPExcel_Exception | |||
{ | |||
/** | |||
* Error handler callback | |||
* | |||
* @param mixed $code | |||
* @param mixed $string | |||
* @param mixed $file | |||
* @param mixed $line | |||
* @param mixed $context | |||
*/ | |||
public static function errorHandlerCallback($code, $string, $file, $line, $context) | |||
{ | |||
$e = new self($string, $code); | |||
$e->line = $line; | |||
$e->file = $file; | |||
throw $e; | |||
} | |||
} |
@ -0,0 +1,45 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Calculation_ExceptionHandler | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_ExceptionHandler | |||
{ | |||
/** | |||
* Register errorhandler | |||
*/ | |||
public function __construct() | |||
{ | |||
set_error_handler(array('PHPExcel_Calculation_Exception', 'errorHandlerCallback'), E_ALL); | |||
} | |||
/** | |||
* Unregister errorhandler | |||
*/ | |||
public function __destruct() | |||
{ | |||
restore_error_handler(); | |||
} | |||
} |
@ -0,0 +1,622 @@ | |||
<?php | |||
/* | |||
PARTLY BASED ON: | |||
Copyright (c) 2007 E. W. Bachtal, Inc. | |||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |||
and associated documentation files (the "Software"), to deal in the Software without restriction, | |||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, | |||
subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all copies or substantial | |||
portions of the Software. | |||
The software is provided "as is", without warranty of any kind, express or implied, including but not | |||
limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In | |||
no event shall the authors or copyright holders be liable for any claim, damages or other liability, | |||
whether in an action of contract, tort or otherwise, arising from, out of or in connection with the | |||
software or the use or other dealings in the software. | |||
http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html | |||
http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html | |||
*/ | |||
/** | |||
* PHPExcel_Calculation_FormulaParser | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_FormulaParser | |||
{ | |||
/* Character constants */ | |||
const QUOTE_DOUBLE = '"'; | |||
const QUOTE_SINGLE = '\''; | |||
const BRACKET_CLOSE = ']'; | |||
const BRACKET_OPEN = '['; | |||
const BRACE_OPEN = '{'; | |||
const BRACE_CLOSE = '}'; | |||
const PAREN_OPEN = '('; | |||
const PAREN_CLOSE = ')'; | |||
const SEMICOLON = ';'; | |||
const WHITESPACE = ' '; | |||
const COMMA = ','; | |||
const ERROR_START = '#'; | |||
const OPERATORS_SN = "+-"; | |||
const OPERATORS_INFIX = "+-*/^&=><"; | |||
const OPERATORS_POSTFIX = "%"; | |||
/** | |||
* Formula | |||
* | |||
* @var string | |||
*/ | |||
private $formula; | |||
/** | |||
* Tokens | |||
* | |||
* @var PHPExcel_Calculation_FormulaToken[] | |||
*/ | |||
private $tokens = array(); | |||
/** | |||
* Create a new PHPExcel_Calculation_FormulaParser | |||
* | |||
* @param string $pFormula Formula to parse | |||
* @throws PHPExcel_Calculation_Exception | |||
*/ | |||
public function __construct($pFormula = '') | |||
{ | |||
// Check parameters | |||
if (is_null($pFormula)) { | |||
throw new PHPExcel_Calculation_Exception("Invalid parameter passed: formula"); | |||
} | |||
// Initialise values | |||
$this->formula = trim($pFormula); | |||
// Parse! | |||
$this->parseToTokens(); | |||
} | |||
/** | |||
* Get Formula | |||
* | |||
* @return string | |||
*/ | |||
public function getFormula() | |||
{ | |||
return $this->formula; | |||
} | |||
/** | |||
* Get Token | |||
* | |||
* @param int $pId Token id | |||
* @return string | |||
* @throws PHPExcel_Calculation_Exception | |||
*/ | |||
public function getToken($pId = 0) | |||
{ | |||
if (isset($this->tokens[$pId])) { | |||
return $this->tokens[$pId]; | |||
} else { | |||
throw new PHPExcel_Calculation_Exception("Token with id $pId does not exist."); | |||
} | |||
} | |||
/** | |||
* Get Token count | |||
* | |||
* @return string | |||
*/ | |||
public function getTokenCount() | |||
{ | |||
return count($this->tokens); | |||
} | |||
/** | |||
* Get Tokens | |||
* | |||
* @return PHPExcel_Calculation_FormulaToken[] | |||
*/ | |||
public function getTokens() | |||
{ | |||
return $this->tokens; | |||
} | |||
/** | |||
* Parse to tokens | |||
*/ | |||
private function parseToTokens() | |||
{ | |||
// No attempt is made to verify formulas; assumes formulas are derived from Excel, where | |||
// they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions. | |||
// Check if the formula has a valid starting = | |||
$formulaLength = strlen($this->formula); | |||
if ($formulaLength < 2 || $this->formula[0] != '=') { | |||
return; | |||
} | |||
// Helper variables | |||
$tokens1 = $tokens2 = $stack = array(); | |||
$inString = $inPath = $inRange = $inError = false; | |||
$token = $previousToken = $nextToken = null; | |||
$index = 1; | |||
$value = ''; | |||
$ERRORS = array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A"); | |||
$COMPARATORS_MULTI = array(">=", "<=", "<>"); | |||
while ($index < $formulaLength) { | |||
// state-dependent character evaluation (order is important) | |||
// double-quoted strings | |||
// embeds are doubled | |||
// end marks token | |||
if ($inString) { | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) { | |||
if ((($index + 2) <= $formulaLength) && ($this->formula[$index + 1] == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) { | |||
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE; | |||
++$index; | |||
} else { | |||
$inString = false; | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT); | |||
$value = ""; | |||
} | |||
} else { | |||
$value .= $this->formula[$index]; | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// single-quoted strings (links) | |||
// embeds are double | |||
// end does not mark a token | |||
if ($inPath) { | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) { | |||
if ((($index + 2) <= $formulaLength) && ($this->formula[$index + 1] == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) { | |||
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE; | |||
++$index; | |||
} else { | |||
$inPath = false; | |||
} | |||
} else { | |||
$value .= $this->formula[$index]; | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// bracked strings (R1C1 range index or linked workbook name) | |||
// no embeds (changed to "()" by Excel) | |||
// end does not mark a token | |||
if ($inRange) { | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) { | |||
$inRange = false; | |||
} | |||
$value .= $this->formula[$index]; | |||
++$index; | |||
continue; | |||
} | |||
// error values | |||
// end marks a token, determined from absolute list of values | |||
if ($inError) { | |||
$value .= $this->formula[$index]; | |||
++$index; | |||
if (in_array($value, $ERRORS)) { | |||
$inError = false; | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR); | |||
$value = ""; | |||
} | |||
continue; | |||
} | |||
// scientific notation check | |||
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->formula[$index]) !== false) { | |||
if (strlen($value) > 1) { | |||
if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->formula[$index]) != 0) { | |||
$value .= $this->formula[$index]; | |||
++$index; | |||
continue; | |||
} | |||
} | |||
} | |||
// independent character evaluation (order not important) | |||
// establish state-dependent character evaluations | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) { | |||
if (strlen($value > 0)) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$inString = true; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) { | |||
if (strlen($value) > 0) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$inPath = true; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) { | |||
$inRange = true; | |||
$value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::ERROR_START) { | |||
if (strlen($value) > 0) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$inError = true; | |||
$value .= PHPExcel_Calculation_FormulaParser::ERROR_START; | |||
++$index; | |||
continue; | |||
} | |||
// mark start and end of arrays and array rows | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) { | |||
if (strlen($value) > 0) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::SEMICOLON) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
$tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT); | |||
$tokens1[] = $tmp; | |||
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
++$index; | |||
continue; | |||
} | |||
// trim white-space | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::WHITESPACE) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE); | |||
++$index; | |||
while (($this->formula[$index] == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) { | |||
++$index; | |||
} | |||
continue; | |||
} | |||
// multi-character comparators | |||
if (($index + 2) <= $formulaLength) { | |||
if (in_array(substr($this->formula, $index, 2), $COMPARATORS_MULTI)) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); | |||
$index += 2; | |||
continue; | |||
} | |||
} | |||
// standard infix operators | |||
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->formula[$index]) !== false) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->formula[$index], PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX); | |||
++$index; | |||
continue; | |||
} | |||
// standard postfix operators (only one) | |||
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->formula[$index]) !== false) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->formula[$index], PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX); | |||
++$index; | |||
continue; | |||
} | |||
// start subexpression or function | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) { | |||
if (strlen($value) > 0) { | |||
$tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
$value = ""; | |||
} else { | |||
$tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// function, subexpression, or array parameters, or operand unions | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::COMMA) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$stack[] = $tmp; | |||
if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION); | |||
} else { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT); | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// stop subexpression | |||
if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
++$index; | |||
continue; | |||
} | |||
// token accumulation | |||
$value .= $this->formula[$index]; | |||
++$index; | |||
} | |||
// dump remaining accumulation | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
} | |||
// move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections | |||
$tokenCount = count($tokens1); | |||
for ($i = 0; $i < $tokenCount; ++$i) { | |||
$token = $tokens1[$i]; | |||
if (isset($tokens1[$i - 1])) { | |||
$previousToken = $tokens1[$i - 1]; | |||
} else { | |||
$previousToken = null; | |||
} | |||
if (isset($tokens1[$i + 1])) { | |||
$nextToken = $tokens1[$i + 1]; | |||
} else { | |||
$nextToken = null; | |||
} | |||
if (is_null($token)) { | |||
continue; | |||
} | |||
if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) { | |||
$tokens2[] = $token; | |||
continue; | |||
} | |||
if (is_null($previousToken)) { | |||
continue; | |||
} | |||
if (! ( | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) | |||
) ) { | |||
continue; | |||
} | |||
if (is_null($nextToken)) { | |||
continue; | |||
} | |||
if (! ( | |||
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) || | |||
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) || | |||
($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) | |||
) ) { | |||
continue; | |||
} | |||
$tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION); | |||
} | |||
// move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators | |||
// to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names | |||
$this->tokens = array(); | |||
$tokenCount = count($tokens2); | |||
for ($i = 0; $i < $tokenCount; ++$i) { | |||
$token = $tokens2[$i]; | |||
if (isset($tokens2[$i - 1])) { | |||
$previousToken = $tokens2[$i - 1]; | |||
} else { | |||
$previousToken = null; | |||
} | |||
if (isset($tokens2[$i + 1])) { | |||
$nextToken = $tokens2[$i + 1]; | |||
} else { | |||
$nextToken = null; | |||
} | |||
if (is_null($token)) { | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") { | |||
if ($i == 0) { | |||
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX); | |||
} elseif ((($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); | |||
} else { | |||
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX); | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") { | |||
if ($i == 0) { | |||
continue; | |||
} elseif ((($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); | |||
} else { | |||
continue; | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && | |||
$token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { | |||
if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); | |||
} elseif ($token->getValue() == "&") { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION); | |||
} else { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND && | |||
$token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { | |||
if (!is_numeric($token->getValue())) { | |||
if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); | |||
} else { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE); | |||
} | |||
} else { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER); | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) { | |||
if (strlen($token->getValue() > 0)) { | |||
if (substr($token->getValue(), 0, 1) == "@") { | |||
$token->setValue(substr($token->getValue(), 1)); | |||
} | |||
} | |||
} | |||
$this->tokens[] = $token; | |||
} | |||
} | |||
} |
@ -0,0 +1,622 @@ | |||
<?php | |||
/* | |||
PARTLY BASED ON: | |||
Copyright (c) 2007 E. W. Bachtal, Inc. | |||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |||
and associated documentation files (the "Software"), to deal in the Software without restriction, | |||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, | |||
subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all copies or substantial | |||
portions of the Software. | |||
The software is provided "as is", without warranty of any kind, express or implied, including but not | |||
limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In | |||
no event shall the authors or copyright holders be liable for any claim, damages or other liability, | |||
whether in an action of contract, tort or otherwise, arising from, out of or in connection with the | |||
software or the use or other dealings in the software. | |||
http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html | |||
http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html | |||
*/ | |||
/** | |||
* PHPExcel_Calculation_FormulaParser | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_FormulaParser | |||
{ | |||
/* Character constants */ | |||
const QUOTE_DOUBLE = '"'; | |||
const QUOTE_SINGLE = '\''; | |||
const BRACKET_CLOSE = ']'; | |||
const BRACKET_OPEN = '['; | |||
const BRACE_OPEN = '{'; | |||
const BRACE_CLOSE = '}'; | |||
const PAREN_OPEN = '('; | |||
const PAREN_CLOSE = ')'; | |||
const SEMICOLON = ';'; | |||
const WHITESPACE = ' '; | |||
const COMMA = ','; | |||
const ERROR_START = '#'; | |||
const OPERATORS_SN = "+-"; | |||
const OPERATORS_INFIX = "+-*/^&=><"; | |||
const OPERATORS_POSTFIX = "%"; | |||
/** | |||
* Formula | |||
* | |||
* @var string | |||
*/ | |||
private $formula; | |||
/** | |||
* Tokens | |||
* | |||
* @var PHPExcel_Calculation_FormulaToken[] | |||
*/ | |||
private $tokens = array(); | |||
/** | |||
* Create a new PHPExcel_Calculation_FormulaParser | |||
* | |||
* @param string $pFormula Formula to parse | |||
* @throws PHPExcel_Calculation_Exception | |||
*/ | |||
public function __construct($pFormula = '') | |||
{ | |||
// Check parameters | |||
if (is_null($pFormula)) { | |||
throw new PHPExcel_Calculation_Exception("Invalid parameter passed: formula"); | |||
} | |||
// Initialise values | |||
$this->formula = trim($pFormula); | |||
// Parse! | |||
$this->parseToTokens(); | |||
} | |||
/** | |||
* Get Formula | |||
* | |||
* @return string | |||
*/ | |||
public function getFormula() | |||
{ | |||
return $this->formula; | |||
} | |||
/** | |||
* Get Token | |||
* | |||
* @param int $pId Token id | |||
* @return string | |||
* @throws PHPExcel_Calculation_Exception | |||
*/ | |||
public function getToken($pId = 0) | |||
{ | |||
if (isset($this->tokens[$pId])) { | |||
return $this->tokens[$pId]; | |||
} else { | |||
throw new PHPExcel_Calculation_Exception("Token with id $pId does not exist."); | |||
} | |||
} | |||
/** | |||
* Get Token count | |||
* | |||
* @return string | |||
*/ | |||
public function getTokenCount() | |||
{ | |||
return count($this->tokens); | |||
} | |||
/** | |||
* Get Tokens | |||
* | |||
* @return PHPExcel_Calculation_FormulaToken[] | |||
*/ | |||
public function getTokens() | |||
{ | |||
return $this->tokens; | |||
} | |||
/** | |||
* Parse to tokens | |||
*/ | |||
private function parseToTokens() | |||
{ | |||
// No attempt is made to verify formulas; assumes formulas are derived from Excel, where | |||
// they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions. | |||
// Check if the formula has a valid starting = | |||
$formulaLength = strlen($this->formula); | |||
if ($formulaLength < 2 || $this->formula{0} != '=') { | |||
return; | |||
} | |||
// Helper variables | |||
$tokens1 = $tokens2 = $stack = array(); | |||
$inString = $inPath = $inRange = $inError = false; | |||
$token = $previousToken = $nextToken = null; | |||
$index = 1; | |||
$value = ''; | |||
$ERRORS = array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A"); | |||
$COMPARATORS_MULTI = array(">=", "<=", "<>"); | |||
while ($index < $formulaLength) { | |||
// state-dependent character evaluation (order is important) | |||
// double-quoted strings | |||
// embeds are doubled | |||
// end marks token | |||
if ($inString) { | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) { | |||
if ((($index + 2) <= $formulaLength) && ($this->formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) { | |||
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE; | |||
++$index; | |||
} else { | |||
$inString = false; | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT); | |||
$value = ""; | |||
} | |||
} else { | |||
$value .= $this->formula{$index}; | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// single-quoted strings (links) | |||
// embeds are double | |||
// end does not mark a token | |||
if ($inPath) { | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) { | |||
if ((($index + 2) <= $formulaLength) && ($this->formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) { | |||
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE; | |||
++$index; | |||
} else { | |||
$inPath = false; | |||
} | |||
} else { | |||
$value .= $this->formula{$index}; | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// bracked strings (R1C1 range index or linked workbook name) | |||
// no embeds (changed to "()" by Excel) | |||
// end does not mark a token | |||
if ($inRange) { | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) { | |||
$inRange = false; | |||
} | |||
$value .= $this->formula{$index}; | |||
++$index; | |||
continue; | |||
} | |||
// error values | |||
// end marks a token, determined from absolute list of values | |||
if ($inError) { | |||
$value .= $this->formula{$index}; | |||
++$index; | |||
if (in_array($value, $ERRORS)) { | |||
$inError = false; | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR); | |||
$value = ""; | |||
} | |||
continue; | |||
} | |||
// scientific notation check | |||
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->formula{$index}) !== false) { | |||
if (strlen($value) > 1) { | |||
if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->formula{$index}) != 0) { | |||
$value .= $this->formula{$index}; | |||
++$index; | |||
continue; | |||
} | |||
} | |||
} | |||
// independent character evaluation (order not important) | |||
// establish state-dependent character evaluations | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) { | |||
if (strlen($value > 0)) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$inString = true; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) { | |||
if (strlen($value) > 0) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$inPath = true; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) { | |||
$inRange = true; | |||
$value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::ERROR_START) { | |||
if (strlen($value) > 0) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$inError = true; | |||
$value .= PHPExcel_Calculation_FormulaParser::ERROR_START; | |||
++$index; | |||
continue; | |||
} | |||
// mark start and end of arrays and array rows | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) { | |||
if (strlen($value) > 0) { | |||
// unexpected | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); | |||
$value = ""; | |||
} | |||
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::SEMICOLON) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
$tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT); | |||
$tokens1[] = $tmp; | |||
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
++$index; | |||
continue; | |||
} | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
++$index; | |||
continue; | |||
} | |||
// trim white-space | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE); | |||
++$index; | |||
while (($this->formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) { | |||
++$index; | |||
} | |||
continue; | |||
} | |||
// multi-character comparators | |||
if (($index + 2) <= $formulaLength) { | |||
if (in_array(substr($this->formula, $index, 2), $COMPARATORS_MULTI)) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); | |||
$index += 2; | |||
continue; | |||
} | |||
} | |||
// standard infix operators | |||
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->formula{$index}) !== false) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX); | |||
++$index; | |||
continue; | |||
} | |||
// standard postfix operators (only one) | |||
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->formula{$index}) !== false) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX); | |||
++$index; | |||
continue; | |||
} | |||
// start subexpression or function | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) { | |||
if (strlen($value) > 0) { | |||
$tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
$value = ""; | |||
} else { | |||
$tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); | |||
$tokens1[] = $tmp; | |||
$stack[] = clone $tmp; | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// function, subexpression, or array parameters, or operand unions | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::COMMA) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$stack[] = $tmp; | |||
if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION); | |||
} else { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT); | |||
} | |||
++$index; | |||
continue; | |||
} | |||
// stop subexpression | |||
if ($this->formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) { | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
$value = ""; | |||
} | |||
$tmp = array_pop($stack); | |||
$tmp->setValue(""); | |||
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); | |||
$tokens1[] = $tmp; | |||
++$index; | |||
continue; | |||
} | |||
// token accumulation | |||
$value .= $this->formula{$index}; | |||
++$index; | |||
} | |||
// dump remaining accumulation | |||
if (strlen($value) > 0) { | |||
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); | |||
} | |||
// move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections | |||
$tokenCount = count($tokens1); | |||
for ($i = 0; $i < $tokenCount; ++$i) { | |||
$token = $tokens1[$i]; | |||
if (isset($tokens1[$i - 1])) { | |||
$previousToken = $tokens1[$i - 1]; | |||
} else { | |||
$previousToken = null; | |||
} | |||
if (isset($tokens1[$i + 1])) { | |||
$nextToken = $tokens1[$i + 1]; | |||
} else { | |||
$nextToken = null; | |||
} | |||
if (is_null($token)) { | |||
continue; | |||
} | |||
if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) { | |||
$tokens2[] = $token; | |||
continue; | |||
} | |||
if (is_null($previousToken)) { | |||
continue; | |||
} | |||
if (! ( | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) | |||
) ) { | |||
continue; | |||
} | |||
if (is_null($nextToken)) { | |||
continue; | |||
} | |||
if (! ( | |||
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) || | |||
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) || | |||
($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) | |||
) ) { | |||
continue; | |||
} | |||
$tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION); | |||
} | |||
// move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators | |||
// to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names | |||
$this->tokens = array(); | |||
$tokenCount = count($tokens2); | |||
for ($i = 0; $i < $tokenCount; ++$i) { | |||
$token = $tokens2[$i]; | |||
if (isset($tokens2[$i - 1])) { | |||
$previousToken = $tokens2[$i - 1]; | |||
} else { | |||
$previousToken = null; | |||
} | |||
if (isset($tokens2[$i + 1])) { | |||
$nextToken = $tokens2[$i + 1]; | |||
} else { | |||
$nextToken = null; | |||
} | |||
if (is_null($token)) { | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") { | |||
if ($i == 0) { | |||
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX); | |||
} elseif ((($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); | |||
} else { | |||
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX); | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") { | |||
if ($i == 0) { | |||
continue; | |||
} elseif ((($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && | |||
($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) || | |||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); | |||
} else { | |||
continue; | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && | |||
$token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { | |||
if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); | |||
} elseif ($token->getValue() == "&") { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION); | |||
} else { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND && | |||
$token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { | |||
if (!is_numeric($token->getValue())) { | |||
if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); | |||
} else { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE); | |||
} | |||
} else { | |||
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER); | |||
} | |||
$this->tokens[] = $token; | |||
continue; | |||
} | |||
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) { | |||
if (strlen($token->getValue() > 0)) { | |||
if (substr($token->getValue(), 0, 1) == "@") { | |||
$token->setValue(substr($token->getValue(), 1)); | |||
} | |||
} | |||
} | |||
$this->tokens[] = $token; | |||
} | |||
} | |||
} |
@ -0,0 +1,176 @@ | |||
<?php | |||
/* | |||
PARTLY BASED ON: | |||
Copyright (c) 2007 E. W. Bachtal, Inc. | |||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |||
and associated documentation files (the "Software"), to deal in the Software without restriction, | |||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, | |||
subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all copies or substantial | |||
portions of the Software. | |||
The software is provided "as is", without warranty of any kind, express or implied, including but not | |||
limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In | |||
no event shall the authors or copyright holders be liable for any claim, damages or other liability, | |||
whether in an action of contract, tort or otherwise, arising from, out of or in connection with the | |||
software or the use or other dealings in the software. | |||
http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html | |||
http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html | |||
*/ | |||
/** | |||
* PHPExcel_Calculation_FormulaToken | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_FormulaToken | |||
{ | |||
/* Token types */ | |||
const TOKEN_TYPE_NOOP = 'Noop'; | |||
const TOKEN_TYPE_OPERAND = 'Operand'; | |||
const TOKEN_TYPE_FUNCTION = 'Function'; | |||
const TOKEN_TYPE_SUBEXPRESSION = 'Subexpression'; | |||
const TOKEN_TYPE_ARGUMENT = 'Argument'; | |||
const TOKEN_TYPE_OPERATORPREFIX = 'OperatorPrefix'; | |||
const TOKEN_TYPE_OPERATORINFIX = 'OperatorInfix'; | |||
const TOKEN_TYPE_OPERATORPOSTFIX = 'OperatorPostfix'; | |||
const TOKEN_TYPE_WHITESPACE = 'Whitespace'; | |||
const TOKEN_TYPE_UNKNOWN = 'Unknown'; | |||
/* Token subtypes */ | |||
const TOKEN_SUBTYPE_NOTHING = 'Nothing'; | |||
const TOKEN_SUBTYPE_START = 'Start'; | |||
const TOKEN_SUBTYPE_STOP = 'Stop'; | |||
const TOKEN_SUBTYPE_TEXT = 'Text'; | |||
const TOKEN_SUBTYPE_NUMBER = 'Number'; | |||
const TOKEN_SUBTYPE_LOGICAL = 'Logical'; | |||
const TOKEN_SUBTYPE_ERROR = 'Error'; | |||
const TOKEN_SUBTYPE_RANGE = 'Range'; | |||
const TOKEN_SUBTYPE_MATH = 'Math'; | |||
const TOKEN_SUBTYPE_CONCATENATION = 'Concatenation'; | |||
const TOKEN_SUBTYPE_INTERSECTION = 'Intersection'; | |||
const TOKEN_SUBTYPE_UNION = 'Union'; | |||
/** | |||
* Value | |||
* | |||
* @var string | |||
*/ | |||
private $value; | |||
/** | |||
* Token Type (represented by TOKEN_TYPE_*) | |||
* | |||
* @var string | |||
*/ | |||
private $tokenType; | |||
/** | |||
* Token SubType (represented by TOKEN_SUBTYPE_*) | |||
* | |||
* @var string | |||
*/ | |||
private $tokenSubType; | |||
/** | |||
* Create a new PHPExcel_Calculation_FormulaToken | |||
* | |||
* @param string $pValue | |||
* @param string $pTokenType Token type (represented by TOKEN_TYPE_*) | |||
* @param string $pTokenSubType Token Subtype (represented by TOKEN_SUBTYPE_*) | |||
*/ | |||
public function __construct($pValue, $pTokenType = PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN, $pTokenSubType = PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) | |||
{ | |||
// Initialise values | |||
$this->value = $pValue; | |||
$this->tokenType = $pTokenType; | |||
$this->tokenSubType = $pTokenSubType; | |||
} | |||
/** | |||
* Get Value | |||
* | |||
* @return string | |||
*/ | |||
public function getValue() | |||
{ | |||
return $this->value; | |||
} | |||
/** | |||
* Set Value | |||
* | |||
* @param string $value | |||
*/ | |||
public function setValue($value) | |||
{ | |||
$this->value = $value; | |||
} | |||
/** | |||
* Get Token Type (represented by TOKEN_TYPE_*) | |||
* | |||
* @return string | |||
*/ | |||
public function getTokenType() | |||
{ | |||
return $this->tokenType; | |||
} | |||
/** | |||
* Set Token Type | |||
* | |||
* @param string $value | |||
*/ | |||
public function setTokenType($value = PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN) | |||
{ | |||
$this->tokenType = $value; | |||
} | |||
/** | |||
* Get Token SubType (represented by TOKEN_SUBTYPE_*) | |||
* | |||
* @return string | |||
*/ | |||
public function getTokenSubType() | |||
{ | |||
return $this->tokenSubType; | |||
} | |||
/** | |||
* Set Token SubType | |||
* | |||
* @param string $value | |||
*/ | |||
public function setTokenSubType($value = PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) | |||
{ | |||
$this->tokenSubType = $value; | |||
} | |||
} |
@ -0,0 +1,148 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Calculation_Function | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Function | |||
{ | |||
/* Function categories */ | |||
const CATEGORY_CUBE = 'Cube'; | |||
const CATEGORY_DATABASE = 'Database'; | |||
const CATEGORY_DATE_AND_TIME = 'Date and Time'; | |||
const CATEGORY_ENGINEERING = 'Engineering'; | |||
const CATEGORY_FINANCIAL = 'Financial'; | |||
const CATEGORY_INFORMATION = 'Information'; | |||
const CATEGORY_LOGICAL = 'Logical'; | |||
const CATEGORY_LOOKUP_AND_REFERENCE = 'Lookup and Reference'; | |||
const CATEGORY_MATH_AND_TRIG = 'Math and Trig'; | |||
const CATEGORY_STATISTICAL = 'Statistical'; | |||
const CATEGORY_TEXT_AND_DATA = 'Text and Data'; | |||
/** | |||
* Category (represented by CATEGORY_*) | |||
* | |||
* @var string | |||
*/ | |||
private $category; | |||
/** | |||
* Excel name | |||
* | |||
* @var string | |||
*/ | |||
private $excelName; | |||
/** | |||
* PHPExcel name | |||
* | |||
* @var string | |||
*/ | |||
private $phpExcelName; | |||
/** | |||
* Create a new PHPExcel_Calculation_Function | |||
* | |||
* @param string $pCategory Category (represented by CATEGORY_*) | |||
* @param string $pExcelName Excel function name | |||
* @param string $pPHPExcelName PHPExcel function mapping | |||
* @throws PHPExcel_Calculation_Exception | |||
*/ | |||
public function __construct($pCategory = null, $pExcelName = null, $pPHPExcelName = null) | |||
{ | |||
if (($pCategory !== null) && ($pExcelName !== null) && ($pPHPExcelName !== null)) { | |||
// Initialise values | |||
$this->category = $pCategory; | |||
$this->excelName = $pExcelName; | |||
$this->phpExcelName = $pPHPExcelName; | |||
} else { | |||
throw new PHPExcel_Calculation_Exception("Invalid parameters passed."); | |||
} | |||
} | |||
/** | |||
* Get Category (represented by CATEGORY_*) | |||
* | |||
* @return string | |||
*/ | |||
public function getCategory() | |||
{ | |||
return $this->category; | |||
} | |||
/** | |||
* Set Category (represented by CATEGORY_*) | |||
* | |||
* @param string $value | |||
* @throws PHPExcel_Calculation_Exception | |||
*/ | |||
public function setCategory($value = null) | |||
{ | |||
if (!is_null($value)) { | |||
$this->category = $value; | |||
} else { | |||
throw new PHPExcel_Calculation_Exception("Invalid parameter passed."); | |||
} | |||
} | |||
/** | |||
* Get Excel name | |||
* | |||
* @return string | |||
*/ | |||
public function getExcelName() | |||
{ | |||
return $this->excelName; | |||
} | |||
/** | |||
* Set Excel name | |||
* | |||
* @param string $value | |||
*/ | |||
public function setExcelName($value) | |||
{ | |||
$this->excelName = $value; | |||
} | |||
/** | |||
* Get PHPExcel name | |||
* | |||
* @return string | |||
*/ | |||
public function getPHPExcelName() | |||
{ | |||
return $this->phpExcelName; | |||
} | |||
/** | |||
* Set PHPExcel name | |||
* | |||
* @param string $value | |||
*/ | |||
public function setPHPExcelName($value) | |||
{ | |||
$this->phpExcelName = $value; | |||
} | |||
} |
@ -0,0 +1,760 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** MAX_VALUE */ | |||
define('MAX_VALUE', 1.2e308); | |||
/** 2 / PI */ | |||
define('M_2DIVPI', 0.63661977236758134307553505349006); | |||
/** MAX_ITERATIONS */ | |||
define('MAX_ITERATIONS', 256); | |||
/** PRECISION */ | |||
define('PRECISION', 8.88E-016); | |||
/** | |||
* PHPExcel_Calculation_Functions | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Functions | |||
{ | |||
/** constants */ | |||
const COMPATIBILITY_EXCEL = 'Excel'; | |||
const COMPATIBILITY_GNUMERIC = 'Gnumeric'; | |||
const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc'; | |||
const RETURNDATE_PHP_NUMERIC = 'P'; | |||
const RETURNDATE_PHP_OBJECT = 'O'; | |||
const RETURNDATE_EXCEL = 'E'; | |||
/** | |||
* Compatibility mode to use for error checking and responses | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
protected static $compatibilityMode = self::COMPATIBILITY_EXCEL; | |||
/** | |||
* Data Type to use when returning date values | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
protected static $returnDateType = self::RETURNDATE_EXCEL; | |||
/** | |||
* List of error codes | |||
* | |||
* @access private | |||
* @var array | |||
*/ | |||
protected static $errorCodes = array( | |||
'null' => '#NULL!', | |||
'divisionbyzero' => '#DIV/0!', | |||
'value' => '#VALUE!', | |||
'reference' => '#REF!', | |||
'name' => '#NAME?', | |||
'num' => '#NUM!', | |||
'na' => '#N/A', | |||
'gettingdata' => '#GETTING_DATA' | |||
); | |||
/** | |||
* Set the Compatibility Mode | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @param string $compatibilityMode Compatibility Mode | |||
* Permitted values are: | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc' | |||
* @return boolean (Success or Failure) | |||
*/ | |||
public static function setCompatibilityMode($compatibilityMode) | |||
{ | |||
if (($compatibilityMode == self::COMPATIBILITY_EXCEL) || | |||
($compatibilityMode == self::COMPATIBILITY_GNUMERIC) || | |||
($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { | |||
self::$compatibilityMode = $compatibilityMode; | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Return the current Compatibility Mode | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @return string Compatibility Mode | |||
* Possible Return values are: | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc' | |||
*/ | |||
public static function getCompatibilityMode() | |||
{ | |||
return self::$compatibilityMode; | |||
} | |||
/** | |||
* Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object) | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @param string $returnDateType Return Date Format | |||
* Permitted values are: | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E' | |||
* @return boolean Success or failure | |||
*/ | |||
public static function setReturnDateType($returnDateType) | |||
{ | |||
if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) || | |||
($returnDateType == self::RETURNDATE_PHP_OBJECT) || | |||
($returnDateType == self::RETURNDATE_EXCEL)) { | |||
self::$returnDateType = $returnDateType; | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object) | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @return string Return Date Format | |||
* Possible Return values are: | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E' | |||
*/ | |||
public static function getReturnDateType() | |||
{ | |||
return self::$returnDateType; | |||
} | |||
/** | |||
* DUMMY | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #Not Yet Implemented | |||
*/ | |||
public static function DUMMY() | |||
{ | |||
return '#Not Yet Implemented'; | |||
} | |||
/** | |||
* DIV0 | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #Not Yet Implemented | |||
*/ | |||
public static function DIV0() | |||
{ | |||
return self::$errorCodes['divisionbyzero']; | |||
} | |||
/** | |||
* NA | |||
* | |||
* Excel Function: | |||
* =NA() | |||
* | |||
* Returns the error value #N/A | |||
* #N/A is the error value that means "no value is available." | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @return string #N/A! | |||
*/ | |||
public static function NA() | |||
{ | |||
return self::$errorCodes['na']; | |||
} | |||
/** | |||
* NaN | |||
* | |||
* Returns the error value #NUM! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #NUM! | |||
*/ | |||
public static function NaN() | |||
{ | |||
return self::$errorCodes['num']; | |||
} | |||
/** | |||
* NAME | |||
* | |||
* Returns the error value #NAME? | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #NAME? | |||
*/ | |||
public static function NAME() | |||
{ | |||
return self::$errorCodes['name']; | |||
} | |||
/** | |||
* REF | |||
* | |||
* Returns the error value #REF! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #REF! | |||
*/ | |||
public static function REF() | |||
{ | |||
return self::$errorCodes['reference']; | |||
} | |||
/** | |||
* NULL | |||
* | |||
* Returns the error value #NULL! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #NULL! | |||
*/ | |||
public static function NULL() | |||
{ | |||
return self::$errorCodes['null']; | |||
} | |||
/** | |||
* VALUE | |||
* | |||
* Returns the error value #VALUE! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #VALUE! | |||
*/ | |||
public static function VALUE() | |||
{ | |||
return self::$errorCodes['value']; | |||
} | |||
public static function isMatrixValue($idx) | |||
{ | |||
return ((substr_count($idx, '.') <= 1) || (preg_match('/\.[A-Z]/', $idx) > 0)); | |||
} | |||
public static function isValue($idx) | |||
{ | |||
return (substr_count($idx, '.') == 0); | |||
} | |||
public static function isCellValue($idx) | |||
{ | |||
return (substr_count($idx, '.') > 1); | |||
} | |||
public static function ifCondition($condition) | |||
{ | |||
$condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition); | |||
if (!isset($condition[0])) { | |||
$condition = '=""'; | |||
} | |||
if (!in_array($condition[0], array('>', '<', '='))) { | |||
if (!is_numeric($condition)) { | |||
$condition = PHPExcel_Calculation::wrapResult(strtoupper($condition)); | |||
} | |||
return '=' . $condition; | |||
} else { | |||
preg_match('/([<>=]+)(.*)/', $condition, $matches); | |||
list(, $operator, $operand) = $matches; | |||
if (!is_numeric($operand)) { | |||
$operand = str_replace('"', '""', $operand); | |||
$operand = PHPExcel_Calculation::wrapResult(strtoupper($operand)); | |||
} | |||
return $operator.$operand; | |||
} | |||
} | |||
/** | |||
* ERROR_TYPE | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function ERROR_TYPE($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
$i = 1; | |||
foreach (self::$errorCodes as $errorCode) { | |||
if ($value === $errorCode) { | |||
return $i; | |||
} | |||
++$i; | |||
} | |||
return self::NA(); | |||
} | |||
/** | |||
* IS_BLANK | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_BLANK($value = null) | |||
{ | |||
if (!is_null($value)) { | |||
$value = self::flattenSingleValue($value); | |||
} | |||
return is_null($value); | |||
} | |||
/** | |||
* IS_ERR | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_ERR($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return self::IS_ERROR($value) && (!self::IS_NA($value)); | |||
} | |||
/** | |||
* IS_ERROR | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_ERROR($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if (!is_string($value)) { | |||
return false; | |||
} | |||
return in_array($value, array_values(self::$errorCodes)); | |||
} | |||
/** | |||
* IS_NA | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_NA($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return ($value === self::NA()); | |||
} | |||
/** | |||
* IS_EVEN | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_EVEN($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if ($value === null) { | |||
return self::NAME(); | |||
} elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { | |||
return self::VALUE(); | |||
} | |||
return ($value % 2 == 0); | |||
} | |||
/** | |||
* IS_ODD | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_ODD($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if ($value === null) { | |||
return self::NAME(); | |||
} elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { | |||
return self::VALUE(); | |||
} | |||
return (abs($value) % 2 == 1); | |||
} | |||
/** | |||
* IS_NUMBER | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_NUMBER($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if (is_string($value)) { | |||
return false; | |||
} | |||
return is_numeric($value); | |||
} | |||
/** | |||
* IS_LOGICAL | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_LOGICAL($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return is_bool($value); | |||
} | |||
/** | |||
* IS_TEXT | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_TEXT($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return (is_string($value) && !self::IS_ERROR($value)); | |||
} | |||
/** | |||
* IS_NONTEXT | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_NONTEXT($value = null) | |||
{ | |||
return !self::IS_TEXT($value); | |||
} | |||
/** | |||
* VERSION | |||
* | |||
* @return string Version information | |||
*/ | |||
public static function VERSION() | |||
{ | |||
return 'PHPExcel ##VERSION##, ##DATE##'; | |||
} | |||
/** | |||
* N | |||
* | |||
* Returns a value converted to a number | |||
* | |||
* @param value The value you want converted | |||
* @return number N converts values listed in the following table | |||
* If value is or refers to N returns | |||
* A number That number | |||
* A date The serial number of that date | |||
* TRUE 1 | |||
* FALSE 0 | |||
* An error value The error value | |||
* Anything else 0 | |||
*/ | |||
public static function N($value = null) | |||
{ | |||
while (is_array($value)) { | |||
$value = array_shift($value); | |||
} | |||
switch (gettype($value)) { | |||
case 'double': | |||
case 'float': | |||
case 'integer': | |||
return $value; | |||
case 'boolean': | |||
return (integer) $value; | |||
case 'string': | |||
// Errors | |||
if ((strlen($value) > 0) && ($value[0] == '#')) { | |||
return $value; | |||
} | |||
break; | |||
} | |||
return 0; | |||
} | |||
/** | |||
* TYPE | |||
* | |||
* Returns a number that identifies the type of a value | |||
* | |||
* @param value The value you want tested | |||
* @return number N converts values listed in the following table | |||
* If value is or refers to N returns | |||
* A number 1 | |||
* Text 2 | |||
* Logical Value 4 | |||
* An error value 16 | |||
* Array or Matrix 64 | |||
*/ | |||
public static function TYPE($value = null) | |||
{ | |||
$value = self::flattenArrayIndexed($value); | |||
if (is_array($value) && (count($value) > 1)) { | |||
end($value); | |||
$a = key($value); | |||
// Range of cells is an error | |||
if (self::isCellValue($a)) { | |||
return 16; | |||
// Test for Matrix | |||
} elseif (self::isMatrixValue($a)) { | |||
return 64; | |||
} | |||
} elseif (empty($value)) { | |||
// Empty Cell | |||
return 1; | |||
} | |||
$value = self::flattenSingleValue($value); | |||
if (($value === null) || (is_float($value)) || (is_int($value))) { | |||
return 1; | |||
} elseif (is_bool($value)) { | |||
return 4; | |||
} elseif (is_array($value)) { | |||
return 64; | |||
} elseif (is_string($value)) { | |||
// Errors | |||
if ((strlen($value) > 0) && ($value[0] == '#')) { | |||
return 16; | |||
} | |||
return 2; | |||
} | |||
return 0; | |||
} | |||
/** | |||
* Convert a multi-dimensional array to a simple 1-dimensional array | |||
* | |||
* @param array $array Array to be flattened | |||
* @return array Flattened array | |||
*/ | |||
public static function flattenArray($array) | |||
{ | |||
if (!is_array($array)) { | |||
return (array) $array; | |||
} | |||
$arrayValues = array(); | |||
foreach ($array as $value) { | |||
if (is_array($value)) { | |||
foreach ($value as $val) { | |||
if (is_array($val)) { | |||
foreach ($val as $v) { | |||
$arrayValues[] = $v; | |||
} | |||
} else { | |||
$arrayValues[] = $val; | |||
} | |||
} | |||
} else { | |||
$arrayValues[] = $value; | |||
} | |||
} | |||
return $arrayValues; | |||
} | |||
/** | |||
* Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing | |||
* | |||
* @param array $array Array to be flattened | |||
* @return array Flattened array | |||
*/ | |||
public static function flattenArrayIndexed($array) | |||
{ | |||
if (!is_array($array)) { | |||
return (array) $array; | |||
} | |||
$arrayValues = array(); | |||
foreach ($array as $k1 => $value) { | |||
if (is_array($value)) { | |||
foreach ($value as $k2 => $val) { | |||
if (is_array($val)) { | |||
foreach ($val as $k3 => $v) { | |||
$arrayValues[$k1.'.'.$k2.'.'.$k3] = $v; | |||
} | |||
} else { | |||
$arrayValues[$k1.'.'.$k2] = $val; | |||
} | |||
} | |||
} else { | |||
$arrayValues[$k1] = $value; | |||
} | |||
} | |||
return $arrayValues; | |||
} | |||
/** | |||
* Convert an array to a single scalar value by extracting the first element | |||
* | |||
* @param mixed $value Array or scalar value | |||
* @return mixed | |||
*/ | |||
public static function flattenSingleValue($value = '') | |||
{ | |||
while (is_array($value)) { | |||
$value = array_pop($value); | |||
} | |||
return $value; | |||
} | |||
} | |||
// | |||
// There are a few mathematical functions that aren't available on all versions of PHP for all platforms | |||
// These functions aren't available in Windows implementations of PHP prior to version 5.3.0 | |||
// So we test if they do exist for this version of PHP/operating platform; and if not we create them | |||
// | |||
if (!function_exists('acosh')) { | |||
function acosh($x) | |||
{ | |||
return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2)); | |||
} // function acosh() | |||
} | |||
if (!function_exists('asinh')) { | |||
function asinh($x) | |||
{ | |||
return log($x + sqrt(1 + $x * $x)); | |||
} // function asinh() | |||
} | |||
if (!function_exists('atanh')) { | |||
function atanh($x) | |||
{ | |||
return (log(1 + $x) - log(1 - $x)) / 2; | |||
} // function atanh() | |||
} | |||
// | |||
// Strangely, PHP doesn't have a mb_str_replace multibyte function | |||
// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set | |||
// | |||
if ((!function_exists('mb_str_replace')) && | |||
(function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) { | |||
function mb_str_replace($search, $replace, $subject) | |||
{ | |||
if (is_array($subject)) { | |||
$ret = array(); | |||
foreach ($subject as $key => $val) { | |||
$ret[$key] = mb_str_replace($search, $replace, $val); | |||
} | |||
return $ret; | |||
} | |||
foreach ((array) $search as $key => $s) { | |||
if ($s == '' && $s !== 0) { | |||
continue; | |||
} | |||
$r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : ''); | |||
$pos = mb_strpos($subject, $s, 0, 'UTF-8'); | |||
while ($pos !== false) { | |||
$subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8'); | |||
$pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8'); | |||
} | |||
} | |||
return $subject; | |||
} | |||
} |
@ -0,0 +1,760 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** MAX_VALUE */ | |||
define('MAX_VALUE', 1.2e308); | |||
/** 2 / PI */ | |||
define('M_2DIVPI', 0.63661977236758134307553505349006); | |||
/** MAX_ITERATIONS */ | |||
define('MAX_ITERATIONS', 256); | |||
/** PRECISION */ | |||
define('PRECISION', 8.88E-016); | |||
/** | |||
* PHPExcel_Calculation_Functions | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Functions | |||
{ | |||
/** constants */ | |||
const COMPATIBILITY_EXCEL = 'Excel'; | |||
const COMPATIBILITY_GNUMERIC = 'Gnumeric'; | |||
const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc'; | |||
const RETURNDATE_PHP_NUMERIC = 'P'; | |||
const RETURNDATE_PHP_OBJECT = 'O'; | |||
const RETURNDATE_EXCEL = 'E'; | |||
/** | |||
* Compatibility mode to use for error checking and responses | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
protected static $compatibilityMode = self::COMPATIBILITY_EXCEL; | |||
/** | |||
* Data Type to use when returning date values | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
protected static $returnDateType = self::RETURNDATE_EXCEL; | |||
/** | |||
* List of error codes | |||
* | |||
* @access private | |||
* @var array | |||
*/ | |||
protected static $errorCodes = array( | |||
'null' => '#NULL!', | |||
'divisionbyzero' => '#DIV/0!', | |||
'value' => '#VALUE!', | |||
'reference' => '#REF!', | |||
'name' => '#NAME?', | |||
'num' => '#NUM!', | |||
'na' => '#N/A', | |||
'gettingdata' => '#GETTING_DATA' | |||
); | |||
/** | |||
* Set the Compatibility Mode | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @param string $compatibilityMode Compatibility Mode | |||
* Permitted values are: | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc' | |||
* @return boolean (Success or Failure) | |||
*/ | |||
public static function setCompatibilityMode($compatibilityMode) | |||
{ | |||
if (($compatibilityMode == self::COMPATIBILITY_EXCEL) || | |||
($compatibilityMode == self::COMPATIBILITY_GNUMERIC) || | |||
($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { | |||
self::$compatibilityMode = $compatibilityMode; | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Return the current Compatibility Mode | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @return string Compatibility Mode | |||
* Possible Return values are: | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric' | |||
* PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc' | |||
*/ | |||
public static function getCompatibilityMode() | |||
{ | |||
return self::$compatibilityMode; | |||
} | |||
/** | |||
* Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object) | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @param string $returnDateType Return Date Format | |||
* Permitted values are: | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E' | |||
* @return boolean Success or failure | |||
*/ | |||
public static function setReturnDateType($returnDateType) | |||
{ | |||
if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) || | |||
($returnDateType == self::RETURNDATE_PHP_OBJECT) || | |||
($returnDateType == self::RETURNDATE_EXCEL)) { | |||
self::$returnDateType = $returnDateType; | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object) | |||
* | |||
* @access public | |||
* @category Function Configuration | |||
* @return string Return Date Format | |||
* Possible Return values are: | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O' | |||
* PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E' | |||
*/ | |||
public static function getReturnDateType() | |||
{ | |||
return self::$returnDateType; | |||
} | |||
/** | |||
* DUMMY | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #Not Yet Implemented | |||
*/ | |||
public static function DUMMY() | |||
{ | |||
return '#Not Yet Implemented'; | |||
} | |||
/** | |||
* DIV0 | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #Not Yet Implemented | |||
*/ | |||
public static function DIV0() | |||
{ | |||
return self::$errorCodes['divisionbyzero']; | |||
} | |||
/** | |||
* NA | |||
* | |||
* Excel Function: | |||
* =NA() | |||
* | |||
* Returns the error value #N/A | |||
* #N/A is the error value that means "no value is available." | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @return string #N/A! | |||
*/ | |||
public static function NA() | |||
{ | |||
return self::$errorCodes['na']; | |||
} | |||
/** | |||
* NaN | |||
* | |||
* Returns the error value #NUM! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #NUM! | |||
*/ | |||
public static function NaN() | |||
{ | |||
return self::$errorCodes['num']; | |||
} | |||
/** | |||
* NAME | |||
* | |||
* Returns the error value #NAME? | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #NAME? | |||
*/ | |||
public static function NAME() | |||
{ | |||
return self::$errorCodes['name']; | |||
} | |||
/** | |||
* REF | |||
* | |||
* Returns the error value #REF! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #REF! | |||
*/ | |||
public static function REF() | |||
{ | |||
return self::$errorCodes['reference']; | |||
} | |||
/** | |||
* NULL | |||
* | |||
* Returns the error value #NULL! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #NULL! | |||
*/ | |||
public static function NULL() | |||
{ | |||
return self::$errorCodes['null']; | |||
} | |||
/** | |||
* VALUE | |||
* | |||
* Returns the error value #VALUE! | |||
* | |||
* @access public | |||
* @category Error Returns | |||
* @return string #VALUE! | |||
*/ | |||
public static function VALUE() | |||
{ | |||
return self::$errorCodes['value']; | |||
} | |||
public static function isMatrixValue($idx) | |||
{ | |||
return ((substr_count($idx, '.') <= 1) || (preg_match('/\.[A-Z]/', $idx) > 0)); | |||
} | |||
public static function isValue($idx) | |||
{ | |||
return (substr_count($idx, '.') == 0); | |||
} | |||
public static function isCellValue($idx) | |||
{ | |||
return (substr_count($idx, '.') > 1); | |||
} | |||
public static function ifCondition($condition) | |||
{ | |||
$condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition); | |||
if (!isset($condition{0})) { | |||
$condition = '=""'; | |||
} | |||
if (!in_array($condition{0}, array('>', '<', '='))) { | |||
if (!is_numeric($condition)) { | |||
$condition = PHPExcel_Calculation::wrapResult(strtoupper($condition)); | |||
} | |||
return '=' . $condition; | |||
} else { | |||
preg_match('/([<>=]+)(.*)/', $condition, $matches); | |||
list(, $operator, $operand) = $matches; | |||
if (!is_numeric($operand)) { | |||
$operand = str_replace('"', '""', $operand); | |||
$operand = PHPExcel_Calculation::wrapResult(strtoupper($operand)); | |||
} | |||
return $operator.$operand; | |||
} | |||
} | |||
/** | |||
* ERROR_TYPE | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function ERROR_TYPE($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
$i = 1; | |||
foreach (self::$errorCodes as $errorCode) { | |||
if ($value === $errorCode) { | |||
return $i; | |||
} | |||
++$i; | |||
} | |||
return self::NA(); | |||
} | |||
/** | |||
* IS_BLANK | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_BLANK($value = null) | |||
{ | |||
if (!is_null($value)) { | |||
$value = self::flattenSingleValue($value); | |||
} | |||
return is_null($value); | |||
} | |||
/** | |||
* IS_ERR | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_ERR($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return self::IS_ERROR($value) && (!self::IS_NA($value)); | |||
} | |||
/** | |||
* IS_ERROR | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_ERROR($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if (!is_string($value)) { | |||
return false; | |||
} | |||
return in_array($value, array_values(self::$errorCodes)); | |||
} | |||
/** | |||
* IS_NA | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_NA($value = '') | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return ($value === self::NA()); | |||
} | |||
/** | |||
* IS_EVEN | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_EVEN($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if ($value === null) { | |||
return self::NAME(); | |||
} elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { | |||
return self::VALUE(); | |||
} | |||
return ($value % 2 == 0); | |||
} | |||
/** | |||
* IS_ODD | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_ODD($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if ($value === null) { | |||
return self::NAME(); | |||
} elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { | |||
return self::VALUE(); | |||
} | |||
return (abs($value) % 2 == 1); | |||
} | |||
/** | |||
* IS_NUMBER | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_NUMBER($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
if (is_string($value)) { | |||
return false; | |||
} | |||
return is_numeric($value); | |||
} | |||
/** | |||
* IS_LOGICAL | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_LOGICAL($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return is_bool($value); | |||
} | |||
/** | |||
* IS_TEXT | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_TEXT($value = null) | |||
{ | |||
$value = self::flattenSingleValue($value); | |||
return (is_string($value) && !self::IS_ERROR($value)); | |||
} | |||
/** | |||
* IS_NONTEXT | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function IS_NONTEXT($value = null) | |||
{ | |||
return !self::IS_TEXT($value); | |||
} | |||
/** | |||
* VERSION | |||
* | |||
* @return string Version information | |||
*/ | |||
public static function VERSION() | |||
{ | |||
return 'PHPExcel ##VERSION##, ##DATE##'; | |||
} | |||
/** | |||
* N | |||
* | |||
* Returns a value converted to a number | |||
* | |||
* @param value The value you want converted | |||
* @return number N converts values listed in the following table | |||
* If value is or refers to N returns | |||
* A number That number | |||
* A date The serial number of that date | |||
* TRUE 1 | |||
* FALSE 0 | |||
* An error value The error value | |||
* Anything else 0 | |||
*/ | |||
public static function N($value = null) | |||
{ | |||
while (is_array($value)) { | |||
$value = array_shift($value); | |||
} | |||
switch (gettype($value)) { | |||
case 'double': | |||
case 'float': | |||
case 'integer': | |||
return $value; | |||
case 'boolean': | |||
return (integer) $value; | |||
case 'string': | |||
// Errors | |||
if ((strlen($value) > 0) && ($value{0} == '#')) { | |||
return $value; | |||
} | |||
break; | |||
} | |||
return 0; | |||
} | |||
/** | |||
* TYPE | |||
* | |||
* Returns a number that identifies the type of a value | |||
* | |||
* @param value The value you want tested | |||
* @return number N converts values listed in the following table | |||
* If value is or refers to N returns | |||
* A number 1 | |||
* Text 2 | |||
* Logical Value 4 | |||
* An error value 16 | |||
* Array or Matrix 64 | |||
*/ | |||
public static function TYPE($value = null) | |||
{ | |||
$value = self::flattenArrayIndexed($value); | |||
if (is_array($value) && (count($value) > 1)) { | |||
end($value); | |||
$a = key($value); | |||
// Range of cells is an error | |||
if (self::isCellValue($a)) { | |||
return 16; | |||
// Test for Matrix | |||
} elseif (self::isMatrixValue($a)) { | |||
return 64; | |||
} | |||
} elseif (empty($value)) { | |||
// Empty Cell | |||
return 1; | |||
} | |||
$value = self::flattenSingleValue($value); | |||
if (($value === null) || (is_float($value)) || (is_int($value))) { | |||
return 1; | |||
} elseif (is_bool($value)) { | |||
return 4; | |||
} elseif (is_array($value)) { | |||
return 64; | |||
} elseif (is_string($value)) { | |||
// Errors | |||
if ((strlen($value) > 0) && ($value{0} == '#')) { | |||
return 16; | |||
} | |||
return 2; | |||
} | |||
return 0; | |||
} | |||
/** | |||
* Convert a multi-dimensional array to a simple 1-dimensional array | |||
* | |||
* @param array $array Array to be flattened | |||
* @return array Flattened array | |||
*/ | |||
public static function flattenArray($array) | |||
{ | |||
if (!is_array($array)) { | |||
return (array) $array; | |||
} | |||
$arrayValues = array(); | |||
foreach ($array as $value) { | |||
if (is_array($value)) { | |||
foreach ($value as $val) { | |||
if (is_array($val)) { | |||
foreach ($val as $v) { | |||
$arrayValues[] = $v; | |||
} | |||
} else { | |||
$arrayValues[] = $val; | |||
} | |||
} | |||
} else { | |||
$arrayValues[] = $value; | |||
} | |||
} | |||
return $arrayValues; | |||
} | |||
/** | |||
* Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing | |||
* | |||
* @param array $array Array to be flattened | |||
* @return array Flattened array | |||
*/ | |||
public static function flattenArrayIndexed($array) | |||
{ | |||
if (!is_array($array)) { | |||
return (array) $array; | |||
} | |||
$arrayValues = array(); | |||
foreach ($array as $k1 => $value) { | |||
if (is_array($value)) { | |||
foreach ($value as $k2 => $val) { | |||
if (is_array($val)) { | |||
foreach ($val as $k3 => $v) { | |||
$arrayValues[$k1.'.'.$k2.'.'.$k3] = $v; | |||
} | |||
} else { | |||
$arrayValues[$k1.'.'.$k2] = $val; | |||
} | |||
} | |||
} else { | |||
$arrayValues[$k1] = $value; | |||
} | |||
} | |||
return $arrayValues; | |||
} | |||
/** | |||
* Convert an array to a single scalar value by extracting the first element | |||
* | |||
* @param mixed $value Array or scalar value | |||
* @return mixed | |||
*/ | |||
public static function flattenSingleValue($value = '') | |||
{ | |||
while (is_array($value)) { | |||
$value = array_pop($value); | |||
} | |||
return $value; | |||
} | |||
} | |||
// | |||
// There are a few mathematical functions that aren't available on all versions of PHP for all platforms | |||
// These functions aren't available in Windows implementations of PHP prior to version 5.3.0 | |||
// So we test if they do exist for this version of PHP/operating platform; and if not we create them | |||
// | |||
if (!function_exists('acosh')) { | |||
function acosh($x) | |||
{ | |||
return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2)); | |||
} // function acosh() | |||
} | |||
if (!function_exists('asinh')) { | |||
function asinh($x) | |||
{ | |||
return log($x + sqrt(1 + $x * $x)); | |||
} // function asinh() | |||
} | |||
if (!function_exists('atanh')) { | |||
function atanh($x) | |||
{ | |||
return (log(1 + $x) - log(1 - $x)) / 2; | |||
} // function atanh() | |||
} | |||
// | |||
// Strangely, PHP doesn't have a mb_str_replace multibyte function | |||
// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set | |||
// | |||
if ((!function_exists('mb_str_replace')) && | |||
(function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) { | |||
function mb_str_replace($search, $replace, $subject) | |||
{ | |||
if (is_array($subject)) { | |||
$ret = array(); | |||
foreach ($subject as $key => $val) { | |||
$ret[$key] = mb_str_replace($search, $replace, $val); | |||
} | |||
return $ret; | |||
} | |||
foreach ((array) $search as $key => $s) { | |||
if ($s == '' && $s !== 0) { | |||
continue; | |||
} | |||
$r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : ''); | |||
$pos = mb_strpos($subject, $s, 0, 'UTF-8'); | |||
while ($pos !== false) { | |||
$subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8'); | |||
$pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8'); | |||
} | |||
} | |||
return $subject; | |||
} | |||
} |
@ -0,0 +1,285 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Calculation_Logical | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Logical | |||
{ | |||
/** | |||
* TRUE | |||
* | |||
* Returns the boolean TRUE. | |||
* | |||
* Excel Function: | |||
* =TRUE() | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @return boolean True | |||
*/ | |||
public static function TRUE() | |||
{ | |||
return true; | |||
} | |||
/** | |||
* FALSE | |||
* | |||
* Returns the boolean FALSE. | |||
* | |||
* Excel Function: | |||
* =FALSE() | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @return boolean False | |||
*/ | |||
public static function FALSE() | |||
{ | |||
return false; | |||
} | |||
/** | |||
* LOGICAL_AND | |||
* | |||
* Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE. | |||
* | |||
* Excel Function: | |||
* =AND(logical1[,logical2[, ...]]) | |||
* | |||
* The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays | |||
* or references that contain logical values. | |||
* | |||
* Boolean arguments are treated as True or False as appropriate | |||
* Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False | |||
* If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds | |||
* the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @param mixed $arg,... Data values | |||
* @return boolean The logical AND of the arguments. | |||
*/ | |||
public static function LOGICAL_AND() | |||
{ | |||
// Return value | |||
$returnValue = true; | |||
// Loop through the arguments | |||
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); | |||
$argCount = -1; | |||
foreach ($aArgs as $argCount => $arg) { | |||
// Is it a boolean value? | |||
if (is_bool($arg)) { | |||
$returnValue = $returnValue && $arg; | |||
} elseif ((is_numeric($arg)) && (!is_string($arg))) { | |||
$returnValue = $returnValue && ($arg != 0); | |||
} elseif (is_string($arg)) { | |||
$arg = strtoupper($arg); | |||
if (($arg == 'TRUE') || ($arg == PHPExcel_Calculation::getTRUE())) { | |||
$arg = true; | |||
} elseif (($arg == 'FALSE') || ($arg == PHPExcel_Calculation::getFALSE())) { | |||
$arg = false; | |||
} else { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
$returnValue = $returnValue && ($arg != 0); | |||
} | |||
} | |||
// Return | |||
if ($argCount < 0) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
return $returnValue; | |||
} | |||
/** | |||
* LOGICAL_OR | |||
* | |||
* Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE. | |||
* | |||
* Excel Function: | |||
* =OR(logical1[,logical2[, ...]]) | |||
* | |||
* The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays | |||
* or references that contain logical values. | |||
* | |||
* Boolean arguments are treated as True or False as appropriate | |||
* Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False | |||
* If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds | |||
* the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @param mixed $arg,... Data values | |||
* @return boolean The logical OR of the arguments. | |||
*/ | |||
public static function LOGICAL_OR() | |||
{ | |||
// Return value | |||
$returnValue = false; | |||
// Loop through the arguments | |||
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); | |||
$argCount = -1; | |||
foreach ($aArgs as $argCount => $arg) { | |||
// Is it a boolean value? | |||
if (is_bool($arg)) { | |||
$returnValue = $returnValue || $arg; | |||
} elseif ((is_numeric($arg)) && (!is_string($arg))) { | |||
$returnValue = $returnValue || ($arg != 0); | |||
} elseif (is_string($arg)) { | |||
$arg = strtoupper($arg); | |||
if (($arg == 'TRUE') || ($arg == PHPExcel_Calculation::getTRUE())) { | |||
$arg = true; | |||
} elseif (($arg == 'FALSE') || ($arg == PHPExcel_Calculation::getFALSE())) { | |||
$arg = false; | |||
} else { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
$returnValue = $returnValue || ($arg != 0); | |||
} | |||
} | |||
// Return | |||
if ($argCount < 0) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
return $returnValue; | |||
} | |||
/** | |||
* NOT | |||
* | |||
* Returns the boolean inverse of the argument. | |||
* | |||
* Excel Function: | |||
* =NOT(logical) | |||
* | |||
* The argument must evaluate to a logical value such as TRUE or FALSE | |||
* | |||
* Boolean arguments are treated as True or False as appropriate | |||
* Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False | |||
* If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds | |||
* the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE | |||
* @return boolean The boolean inverse of the argument. | |||
*/ | |||
public static function NOT($logical = false) | |||
{ | |||
$logical = PHPExcel_Calculation_Functions::flattenSingleValue($logical); | |||
if (is_string($logical)) { | |||
$logical = strtoupper($logical); | |||
if (($logical == 'TRUE') || ($logical == PHPExcel_Calculation::getTRUE())) { | |||
return false; | |||
} elseif (($logical == 'FALSE') || ($logical == PHPExcel_Calculation::getFALSE())) { | |||
return true; | |||
} else { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
} | |||
return !$logical; | |||
} | |||
/** | |||
* STATEMENT_IF | |||
* | |||
* Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE. | |||
* | |||
* Excel Function: | |||
* =IF(condition[,returnIfTrue[,returnIfFalse]]) | |||
* | |||
* Condition is any value or expression that can be evaluated to TRUE or FALSE. | |||
* For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100, | |||
* the expression evaluates to TRUE. Otherwise, the expression evaluates to FALSE. | |||
* This argument can use any comparison calculation operator. | |||
* ReturnIfTrue is the value that is returned if condition evaluates to TRUE. | |||
* For example, if this argument is the text string "Within budget" and the condition argument evaluates to TRUE, | |||
* then the IF function returns the text "Within budget" | |||
* If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). To display the word TRUE, use | |||
* the logical value TRUE for this argument. | |||
* ReturnIfTrue can be another formula. | |||
* ReturnIfFalse is the value that is returned if condition evaluates to FALSE. | |||
* For example, if this argument is the text string "Over budget" and the condition argument evaluates to FALSE, | |||
* then the IF function returns the text "Over budget". | |||
* If condition is FALSE and ReturnIfFalse is omitted, then the logical value FALSE is returned. | |||
* If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. | |||
* ReturnIfFalse can be another formula. | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @param mixed $condition Condition to evaluate | |||
* @param mixed $returnIfTrue Value to return when condition is true | |||
* @param mixed $returnIfFalse Optional value to return when condition is false | |||
* @return mixed The value of returnIfTrue or returnIfFalse determined by condition | |||
*/ | |||
public static function STATEMENT_IF($condition = true, $returnIfTrue = 0, $returnIfFalse = false) | |||
{ | |||
$condition = (is_null($condition)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($condition); | |||
$returnIfTrue = (is_null($returnIfTrue)) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($returnIfTrue); | |||
$returnIfFalse = (is_null($returnIfFalse)) ? false : PHPExcel_Calculation_Functions::flattenSingleValue($returnIfFalse); | |||
return ($condition) ? $returnIfTrue : $returnIfFalse; | |||
} | |||
/** | |||
* IFERROR | |||
* | |||
* Excel Function: | |||
* =IFERROR(testValue,errorpart) | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @param mixed $testValue Value to check, is also the value returned when no error | |||
* @param mixed $errorpart Value to return when testValue is an error condition | |||
* @return mixed The value of errorpart or testValue determined by error condition | |||
*/ | |||
public static function IFERROR($testValue = '', $errorpart = '') | |||
{ | |||
$testValue = (is_null($testValue)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($testValue); | |||
$errorpart = (is_null($errorpart)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($errorpart); | |||
return self::STATEMENT_IF(PHPExcel_Calculation_Functions::IS_ERROR($testValue), $errorpart, $testValue); | |||
} | |||
} |
@ -0,0 +1,879 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Calculation_LookupRef | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_LookupRef | |||
{ | |||
/** | |||
* CELL_ADDRESS | |||
* | |||
* Creates a cell address as text, given specified row and column numbers. | |||
* | |||
* Excel Function: | |||
* =ADDRESS(row, column, [relativity], [referenceStyle], [sheetText]) | |||
* | |||
* @param row Row number to use in the cell reference | |||
* @param column Column number to use in the cell reference | |||
* @param relativity Flag indicating the type of reference to return | |||
* 1 or omitted Absolute | |||
* 2 Absolute row; relative column | |||
* 3 Relative row; absolute column | |||
* 4 Relative | |||
* @param referenceStyle A logical value that specifies the A1 or R1C1 reference style. | |||
* TRUE or omitted CELL_ADDRESS returns an A1-style reference | |||
* FALSE CELL_ADDRESS returns an R1C1-style reference | |||
* @param sheetText Optional Name of worksheet to use | |||
* @return string | |||
*/ | |||
public static function CELL_ADDRESS($row, $column, $relativity = 1, $referenceStyle = true, $sheetText = '') | |||
{ | |||
$row = PHPExcel_Calculation_Functions::flattenSingleValue($row); | |||
$column = PHPExcel_Calculation_Functions::flattenSingleValue($column); | |||
$relativity = PHPExcel_Calculation_Functions::flattenSingleValue($relativity); | |||
$sheetText = PHPExcel_Calculation_Functions::flattenSingleValue($sheetText); | |||
if (($row < 1) || ($column < 1)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if ($sheetText > '') { | |||
if (strpos($sheetText, ' ') !== false) { | |||
$sheetText = "'".$sheetText."'"; | |||
} | |||
$sheetText .='!'; | |||
} | |||
if ((!is_bool($referenceStyle)) || $referenceStyle) { | |||
$rowRelative = $columnRelative = '$'; | |||
$column = PHPExcel_Cell::stringFromColumnIndex($column-1); | |||
if (($relativity == 2) || ($relativity == 4)) { | |||
$columnRelative = ''; | |||
} | |||
if (($relativity == 3) || ($relativity == 4)) { | |||
$rowRelative = ''; | |||
} | |||
return $sheetText.$columnRelative.$column.$rowRelative.$row; | |||
} else { | |||
if (($relativity == 2) || ($relativity == 4)) { | |||
$column = '['.$column.']'; | |||
} | |||
if (($relativity == 3) || ($relativity == 4)) { | |||
$row = '['.$row.']'; | |||
} | |||
return $sheetText.'R'.$row.'C'.$column; | |||
} | |||
} | |||
/** | |||
* COLUMN | |||
* | |||
* Returns the column number of the given cell reference | |||
* If the cell reference is a range of cells, COLUMN returns the column numbers of each column in the reference as a horizontal array. | |||
* If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the | |||
* reference of the cell in which the COLUMN function appears; otherwise this function returns 0. | |||
* | |||
* Excel Function: | |||
* =COLUMN([cellAddress]) | |||
* | |||
* @param cellAddress A reference to a range of cells for which you want the column numbers | |||
* @return integer or array of integer | |||
*/ | |||
public static function COLUMN($cellAddress = null) | |||
{ | |||
if (is_null($cellAddress) || trim($cellAddress) === '') { | |||
return 0; | |||
} | |||
if (is_array($cellAddress)) { | |||
foreach ($cellAddress as $columnKey => $value) { | |||
$columnKey = preg_replace('/[^a-z]/i', '', $columnKey); | |||
return (integer) PHPExcel_Cell::columnIndexFromString($columnKey); | |||
} | |||
} else { | |||
if (strpos($cellAddress, '!') !== false) { | |||
list($sheet, $cellAddress) = explode('!', $cellAddress); | |||
} | |||
if (strpos($cellAddress, ':') !== false) { | |||
list($startAddress, $endAddress) = explode(':', $cellAddress); | |||
$startAddress = preg_replace('/[^a-z]/i', '', $startAddress); | |||
$endAddress = preg_replace('/[^a-z]/i', '', $endAddress); | |||
$returnValue = array(); | |||
do { | |||
$returnValue[] = (integer) PHPExcel_Cell::columnIndexFromString($startAddress); | |||
} while ($startAddress++ != $endAddress); | |||
return $returnValue; | |||
} else { | |||
$cellAddress = preg_replace('/[^a-z]/i', '', $cellAddress); | |||
return (integer) PHPExcel_Cell::columnIndexFromString($cellAddress); | |||
} | |||
} | |||
} | |||
/** | |||
* COLUMNS | |||
* | |||
* Returns the number of columns in an array or reference. | |||
* | |||
* Excel Function: | |||
* =COLUMNS(cellAddress) | |||
* | |||
* @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns | |||
* @return integer The number of columns in cellAddress | |||
*/ | |||
public static function COLUMNS($cellAddress = null) | |||
{ | |||
if (is_null($cellAddress) || $cellAddress === '') { | |||
return 1; | |||
} elseif (!is_array($cellAddress)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
reset($cellAddress); | |||
$isMatrix = (is_numeric(key($cellAddress))); | |||
list($columns, $rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); | |||
if ($isMatrix) { | |||
return $rows; | |||
} else { | |||
return $columns; | |||
} | |||
} | |||
/** | |||
* ROW | |||
* | |||
* Returns the row number of the given cell reference | |||
* If the cell reference is a range of cells, ROW returns the row numbers of each row in the reference as a vertical array. | |||
* If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the | |||
* reference of the cell in which the ROW function appears; otherwise this function returns 0. | |||
* | |||
* Excel Function: | |||
* =ROW([cellAddress]) | |||
* | |||
* @param cellAddress A reference to a range of cells for which you want the row numbers | |||
* @return integer or array of integer | |||
*/ | |||
public static function ROW($cellAddress = null) | |||
{ | |||
if (is_null($cellAddress) || trim($cellAddress) === '') { | |||
return 0; | |||
} | |||
if (is_array($cellAddress)) { | |||
foreach ($cellAddress as $columnKey => $rowValue) { | |||
foreach ($rowValue as $rowKey => $cellValue) { | |||
return (integer) preg_replace('/[^0-9]/i', '', $rowKey); | |||
} | |||
} | |||
} else { | |||
if (strpos($cellAddress, '!') !== false) { | |||
list($sheet, $cellAddress) = explode('!', $cellAddress); | |||
} | |||
if (strpos($cellAddress, ':') !== false) { | |||
list($startAddress, $endAddress) = explode(':', $cellAddress); | |||
$startAddress = preg_replace('/[^0-9]/', '', $startAddress); | |||
$endAddress = preg_replace('/[^0-9]/', '', $endAddress); | |||
$returnValue = array(); | |||
do { | |||
$returnValue[][] = (integer) $startAddress; | |||
} while ($startAddress++ != $endAddress); | |||
return $returnValue; | |||
} else { | |||
list($cellAddress) = explode(':', $cellAddress); | |||
return (integer) preg_replace('/[^0-9]/', '', $cellAddress); | |||
} | |||
} | |||
} | |||
/** | |||
* ROWS | |||
* | |||
* Returns the number of rows in an array or reference. | |||
* | |||
* Excel Function: | |||
* =ROWS(cellAddress) | |||
* | |||
* @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows | |||
* @return integer The number of rows in cellAddress | |||
*/ | |||
public static function ROWS($cellAddress = null) | |||
{ | |||
if (is_null($cellAddress) || $cellAddress === '') { | |||
return 1; | |||
} elseif (!is_array($cellAddress)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
reset($cellAddress); | |||
$isMatrix = (is_numeric(key($cellAddress))); | |||
list($columns, $rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); | |||
if ($isMatrix) { | |||
return $columns; | |||
} else { | |||
return $rows; | |||
} | |||
} | |||
/** | |||
* HYPERLINK | |||
* | |||
* Excel Function: | |||
* =HYPERLINK(linkURL,displayName) | |||
* | |||
* @access public | |||
* @category Logical Functions | |||
* @param string $linkURL Value to check, is also the value returned when no error | |||
* @param string $displayName Value to return when testValue is an error condition | |||
* @param PHPExcel_Cell $pCell The cell to set the hyperlink in | |||
* @return mixed The value of $displayName (or $linkURL if $displayName was blank) | |||
*/ | |||
public static function HYPERLINK($linkURL = '', $displayName = null, PHPExcel_Cell $pCell = null) | |||
{ | |||
$args = func_get_args(); | |||
$pCell = array_pop($args); | |||
$linkURL = (is_null($linkURL)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($linkURL); | |||
$displayName = (is_null($displayName)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($displayName); | |||
if ((!is_object($pCell)) || (trim($linkURL) == '')) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
if ((is_object($displayName)) || trim($displayName) == '') { | |||
$displayName = $linkURL; | |||
} | |||
$pCell->getHyperlink()->setUrl($linkURL); | |||
$pCell->getHyperlink()->setTooltip($displayName); | |||
return $displayName; | |||
} | |||
/** | |||
* INDIRECT | |||
* | |||
* Returns the reference specified by a text string. | |||
* References are immediately evaluated to display their contents. | |||
* | |||
* Excel Function: | |||
* =INDIRECT(cellAddress) | |||
* | |||
* NOTE - INDIRECT() does not yet support the optional a1 parameter introduced in Excel 2010 | |||
* | |||
* @param cellAddress $cellAddress The cell address of the current cell (containing this formula) | |||
* @param PHPExcel_Cell $pCell The current cell (containing this formula) | |||
* @return mixed The cells referenced by cellAddress | |||
* | |||
* @todo Support for the optional a1 parameter introduced in Excel 2010 | |||
* | |||
*/ | |||
public static function INDIRECT($cellAddress = null, PHPExcel_Cell $pCell = null) | |||
{ | |||
$cellAddress = PHPExcel_Calculation_Functions::flattenSingleValue($cellAddress); | |||
if (is_null($cellAddress) || $cellAddress === '') { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
$cellAddress1 = $cellAddress; | |||
$cellAddress2 = null; | |||
if (strpos($cellAddress, ':') !== false) { | |||
list($cellAddress1, $cellAddress2) = explode(':', $cellAddress); | |||
} | |||
if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress1, $matches)) || | |||
((!is_null($cellAddress2)) && (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress2, $matches)))) { | |||
if (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $cellAddress1, $matches)) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
if (strpos($cellAddress, '!') !== false) { | |||
list($sheetName, $cellAddress) = explode('!', $cellAddress); | |||
$sheetName = trim($sheetName, "'"); | |||
$pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); | |||
} else { | |||
$pSheet = $pCell->getWorksheet(); | |||
} | |||
return PHPExcel_Calculation::getInstance()->extractNamedRange($cellAddress, $pSheet, false); | |||
} | |||
if (strpos($cellAddress, '!') !== false) { | |||
list($sheetName, $cellAddress) = explode('!', $cellAddress); | |||
$sheetName = trim($sheetName, "'"); | |||
$pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); | |||
} else { | |||
$pSheet = $pCell->getWorksheet(); | |||
} | |||
return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, false); | |||
} | |||
/** | |||
* OFFSET | |||
* | |||
* Returns a reference to a range that is a specified number of rows and columns from a cell or range of cells. | |||
* The reference that is returned can be a single cell or a range of cells. You can specify the number of rows and | |||
* the number of columns to be returned. | |||
* | |||
* Excel Function: | |||
* =OFFSET(cellAddress, rows, cols, [height], [width]) | |||
* | |||
* @param cellAddress The reference from which you want to base the offset. Reference must refer to a cell or | |||
* range of adjacent cells; otherwise, OFFSET returns the #VALUE! error value. | |||
* @param rows The number of rows, up or down, that you want the upper-left cell to refer to. | |||
* Using 5 as the rows argument specifies that the upper-left cell in the reference is | |||
* five rows below reference. Rows can be positive (which means below the starting reference) | |||
* or negative (which means above the starting reference). | |||
* @param cols The number of columns, to the left or right, that you want the upper-left cell of the result | |||
* to refer to. Using 5 as the cols argument specifies that the upper-left cell in the | |||
* reference is five columns to the right of reference. Cols can be positive (which means | |||
* to the right of the starting reference) or negative (which means to the left of the | |||
* starting reference). | |||
* @param height The height, in number of rows, that you want the returned reference to be. Height must be a positive number. | |||
* @param width The width, in number of columns, that you want the returned reference to be. Width must be a positive number. | |||
* @return string A reference to a cell or range of cells | |||
*/ | |||
public static function OFFSET($cellAddress = null, $rows = 0, $columns = 0, $height = null, $width = null) | |||
{ | |||
$rows = PHPExcel_Calculation_Functions::flattenSingleValue($rows); | |||
$columns = PHPExcel_Calculation_Functions::flattenSingleValue($columns); | |||
$height = PHPExcel_Calculation_Functions::flattenSingleValue($height); | |||
$width = PHPExcel_Calculation_Functions::flattenSingleValue($width); | |||
if ($cellAddress == null) { | |||
return 0; | |||
} | |||
$args = func_get_args(); | |||
$pCell = array_pop($args); | |||
if (!is_object($pCell)) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
$sheetName = null; | |||
if (strpos($cellAddress, "!")) { | |||
list($sheetName, $cellAddress) = explode("!", $cellAddress); | |||
$sheetName = trim($sheetName, "'"); | |||
} | |||
if (strpos($cellAddress, ":")) { | |||
list($startCell, $endCell) = explode(":", $cellAddress); | |||
} else { | |||
$startCell = $endCell = $cellAddress; | |||
} | |||
list($startCellColumn, $startCellRow) = PHPExcel_Cell::coordinateFromString($startCell); | |||
list($endCellColumn, $endCellRow) = PHPExcel_Cell::coordinateFromString($endCell); | |||
$startCellRow += $rows; | |||
$startCellColumn = PHPExcel_Cell::columnIndexFromString($startCellColumn) - 1; | |||
$startCellColumn += $columns; | |||
if (($startCellRow <= 0) || ($startCellColumn < 0)) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
$endCellColumn = PHPExcel_Cell::columnIndexFromString($endCellColumn) - 1; | |||
if (($width != null) && (!is_object($width))) { | |||
$endCellColumn = $startCellColumn + $width - 1; | |||
} else { | |||
$endCellColumn += $columns; | |||
} | |||
$startCellColumn = PHPExcel_Cell::stringFromColumnIndex($startCellColumn); | |||
if (($height != null) && (!is_object($height))) { | |||
$endCellRow = $startCellRow + $height - 1; | |||
} else { | |||
$endCellRow += $rows; | |||
} | |||
if (($endCellRow <= 0) || ($endCellColumn < 0)) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
$endCellColumn = PHPExcel_Cell::stringFromColumnIndex($endCellColumn); | |||
$cellAddress = $startCellColumn.$startCellRow; | |||
if (($startCellColumn != $endCellColumn) || ($startCellRow != $endCellRow)) { | |||
$cellAddress .= ':'.$endCellColumn.$endCellRow; | |||
} | |||
if ($sheetName !== null) { | |||
$pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); | |||
} else { | |||
$pSheet = $pCell->getWorksheet(); | |||
} | |||
return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, false); | |||
} | |||
/** | |||
* CHOOSE | |||
* | |||
* Uses lookup_value to return a value from the list of value arguments. | |||
* Use CHOOSE to select one of up to 254 values based on the lookup_value. | |||
* | |||
* Excel Function: | |||
* =CHOOSE(index_num, value1, [value2], ...) | |||
* | |||
* @param index_num Specifies which value argument is selected. | |||
* Index_num must be a number between 1 and 254, or a formula or reference to a cell containing a number | |||
* between 1 and 254. | |||
* @param value1... Value1 is required, subsequent values are optional. | |||
* Between 1 to 254 value arguments from which CHOOSE selects a value or an action to perform based on | |||
* index_num. The arguments can be numbers, cell references, defined names, formulas, functions, or | |||
* text. | |||
* @return mixed The selected value | |||
*/ | |||
public static function CHOOSE() | |||
{ | |||
$chooseArgs = func_get_args(); | |||
$chosenEntry = PHPExcel_Calculation_Functions::flattenArray(array_shift($chooseArgs)); | |||
$entryCount = count($chooseArgs) - 1; | |||
if (is_array($chosenEntry)) { | |||
$chosenEntry = array_shift($chosenEntry); | |||
} | |||
if ((is_numeric($chosenEntry)) && (!is_bool($chosenEntry))) { | |||
--$chosenEntry; | |||
} else { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
$chosenEntry = floor($chosenEntry); | |||
if (($chosenEntry < 0) || ($chosenEntry > $entryCount)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_array($chooseArgs[$chosenEntry])) { | |||
return PHPExcel_Calculation_Functions::flattenArray($chooseArgs[$chosenEntry]); | |||
} else { | |||
return $chooseArgs[$chosenEntry]; | |||
} | |||
} | |||
/** | |||
* MATCH | |||
* | |||
* The MATCH function searches for a specified item in a range of cells | |||
* | |||
* Excel Function: | |||
* =MATCH(lookup_value, lookup_array, [match_type]) | |||
* | |||
* @param lookup_value The value that you want to match in lookup_array | |||
* @param lookup_array The range of cells being searched | |||
* @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. | |||
* @return integer The relative position of the found item | |||
*/ | |||
public static function MATCH($lookup_value, $lookup_array, $match_type = 1) | |||
{ | |||
$lookup_array = PHPExcel_Calculation_Functions::flattenArray($lookup_array); | |||
$lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); | |||
$match_type = (is_null($match_type)) ? 1 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($match_type); | |||
// MATCH is not case sensitive | |||
$lookup_value = strtolower($lookup_value); | |||
// lookup_value type has to be number, text, or logical values | |||
if ((!is_numeric($lookup_value)) && (!is_string($lookup_value)) && (!is_bool($lookup_value))) { | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
// match_type is 0, 1 or -1 | |||
if (($match_type !== 0) && ($match_type !== -1) && ($match_type !== 1)) { | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
// lookup_array should not be empty | |||
$lookupArraySize = count($lookup_array); | |||
if ($lookupArraySize <= 0) { | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
// lookup_array should contain only number, text, or logical values, or empty (null) cells | |||
foreach ($lookup_array as $i => $lookupArrayValue) { | |||
// check the type of the value | |||
if ((!is_numeric($lookupArrayValue)) && (!is_string($lookupArrayValue)) && | |||
(!is_bool($lookupArrayValue)) && (!is_null($lookupArrayValue))) { | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
// convert strings to lowercase for case-insensitive testing | |||
if (is_string($lookupArrayValue)) { | |||
$lookup_array[$i] = strtolower($lookupArrayValue); | |||
} | |||
if ((is_null($lookupArrayValue)) && (($match_type == 1) || ($match_type == -1))) { | |||
$lookup_array = array_slice($lookup_array, 0, $i-1); | |||
} | |||
} | |||
// if match_type is 1 or -1, the list has to be ordered | |||
if ($match_type == 1) { | |||
asort($lookup_array); | |||
$keySet = array_keys($lookup_array); | |||
} elseif ($match_type == -1) { | |||
arsort($lookup_array); | |||
$keySet = array_keys($lookup_array); | |||
} | |||
// ** | |||
// find the match | |||
// ** | |||
foreach ($lookup_array as $i => $lookupArrayValue) { | |||
if (($match_type == 0) && ($lookupArrayValue == $lookup_value)) { | |||
// exact match | |||
return ++$i; | |||
} elseif (($match_type == -1) && ($lookupArrayValue <= $lookup_value)) { | |||
$i = array_search($i, $keySet); | |||
// if match_type is -1 <=> find the smallest value that is greater than or equal to lookup_value | |||
if ($i < 1) { | |||
// 1st cell was already smaller than the lookup_value | |||
break; | |||
} else { | |||
// the previous cell was the match | |||
return $keySet[$i-1]+1; | |||
} | |||
} elseif (($match_type == 1) && ($lookupArrayValue >= $lookup_value)) { | |||
$i = array_search($i, $keySet); | |||
// if match_type is 1 <=> find the largest value that is less than or equal to lookup_value | |||
if ($i < 1) { | |||
// 1st cell was already bigger than the lookup_value | |||
break; | |||
} else { | |||
// the previous cell was the match | |||
return $keySet[$i-1]+1; | |||
} | |||
} | |||
} | |||
// unsuccessful in finding a match, return #N/A error value | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
/** | |||
* INDEX | |||
* | |||
* Uses an index to choose a value from a reference or array | |||
* | |||
* Excel Function: | |||
* =INDEX(range_array, row_num, [column_num]) | |||
* | |||
* @param range_array A range of cells or an array constant | |||
* @param row_num The row in array from which to return a value. If row_num is omitted, column_num is required. | |||
* @param column_num The column in array from which to return a value. If column_num is omitted, row_num is required. | |||
* @return mixed the value of a specified cell or array of cells | |||
*/ | |||
public static function INDEX($arrayValues, $rowNum = 0, $columnNum = 0) | |||
{ | |||
if (($rowNum < 0) || ($columnNum < 0)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (!is_array($arrayValues)) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} | |||
$rowKeys = array_keys($arrayValues); | |||
$columnKeys = @array_keys($arrayValues[$rowKeys[0]]); | |||
if ($columnNum > count($columnKeys)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} elseif ($columnNum == 0) { | |||
if ($rowNum == 0) { | |||
return $arrayValues; | |||
} | |||
$rowNum = $rowKeys[--$rowNum]; | |||
$returnArray = array(); | |||
foreach ($arrayValues as $arrayColumn) { | |||
if (is_array($arrayColumn)) { | |||
if (isset($arrayColumn[$rowNum])) { | |||
$returnArray[] = $arrayColumn[$rowNum]; | |||
} else { | |||
return $arrayValues[$rowNum]; | |||
} | |||
} else { | |||
return $arrayValues[$rowNum]; | |||
} | |||
} | |||
return $returnArray; | |||
} | |||
$columnNum = $columnKeys[--$columnNum]; | |||
if ($rowNum > count($rowKeys)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} elseif ($rowNum == 0) { | |||
return $arrayValues[$columnNum]; | |||
} | |||
$rowNum = $rowKeys[--$rowNum]; | |||
return $arrayValues[$rowNum][$columnNum]; | |||
} | |||
/** | |||
* TRANSPOSE | |||
* | |||
* @param array $matrixData A matrix of values | |||
* @return array | |||
* | |||
* Unlike the Excel TRANSPOSE function, which will only work on a single row or column, this function will transpose a full matrix. | |||
*/ | |||
public static function TRANSPOSE($matrixData) | |||
{ | |||
$returnMatrix = array(); | |||
if (!is_array($matrixData)) { | |||
$matrixData = array(array($matrixData)); | |||
} | |||
$column = 0; | |||
foreach ($matrixData as $matrixRow) { | |||
$row = 0; | |||
foreach ($matrixRow as $matrixCell) { | |||
$returnMatrix[$row][$column] = $matrixCell; | |||
++$row; | |||
} | |||
++$column; | |||
} | |||
return $returnMatrix; | |||
} | |||
private static function vlookupSort($a, $b) | |||
{ | |||
reset($a); | |||
$firstColumn = key($a); | |||
if (($aLower = strtolower($a[$firstColumn])) == ($bLower = strtolower($b[$firstColumn]))) { | |||
return 0; | |||
} | |||
return ($aLower < $bLower) ? -1 : 1; | |||
} | |||
/** | |||
* VLOOKUP | |||
* The VLOOKUP function searches for value in the left-most column of lookup_array and returns the value in the same row based on the index_number. | |||
* @param lookup_value The value that you want to match in lookup_array | |||
* @param lookup_array The range of cells being searched | |||
* @param index_number The column number in table_array from which the matching value must be returned. The first column is 1. | |||
* @param not_exact_match Determines if you are looking for an exact match based on lookup_value. | |||
* @return mixed The value of the found cell | |||
*/ | |||
public static function VLOOKUP($lookup_value, $lookup_array, $index_number, $not_exact_match = true) | |||
{ | |||
$lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); | |||
$index_number = PHPExcel_Calculation_Functions::flattenSingleValue($index_number); | |||
$not_exact_match = PHPExcel_Calculation_Functions::flattenSingleValue($not_exact_match); | |||
// index_number must be greater than or equal to 1 | |||
if ($index_number < 1) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
// index_number must be less than or equal to the number of columns in lookup_array | |||
if ((!is_array($lookup_array)) || (empty($lookup_array))) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} else { | |||
$f = array_keys($lookup_array); | |||
$firstRow = array_pop($f); | |||
if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} else { | |||
$columnKeys = array_keys($lookup_array[$firstRow]); | |||
$returnColumn = $columnKeys[--$index_number]; | |||
$firstColumn = array_shift($columnKeys); | |||
} | |||
} | |||
if (!$not_exact_match) { | |||
uasort($lookup_array, array('self', 'vlookupSort')); | |||
} | |||
$rowNumber = $rowValue = false; | |||
foreach ($lookup_array as $rowKey => $rowData) { | |||
if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) || | |||
(!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)))) { | |||
break; | |||
} | |||
$rowNumber = $rowKey; | |||
$rowValue = $rowData[$firstColumn]; | |||
} | |||
if ($rowNumber !== false) { | |||
if ((!$not_exact_match) && ($rowValue != $lookup_value)) { | |||
// if an exact match is required, we have what we need to return an appropriate response | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} else { | |||
// otherwise return the appropriate value | |||
return $lookup_array[$rowNumber][$returnColumn]; | |||
} | |||
} | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
/** | |||
* HLOOKUP | |||
* The HLOOKUP function searches for value in the top-most row of lookup_array and returns the value in the same column based on the index_number. | |||
* @param lookup_value The value that you want to match in lookup_array | |||
* @param lookup_array The range of cells being searched | |||
* @param index_number The row number in table_array from which the matching value must be returned. The first row is 1. | |||
* @param not_exact_match Determines if you are looking for an exact match based on lookup_value. | |||
* @return mixed The value of the found cell | |||
*/ | |||
public static function HLOOKUP($lookup_value, $lookup_array, $index_number, $not_exact_match = true) | |||
{ | |||
$lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); | |||
$index_number = PHPExcel_Calculation_Functions::flattenSingleValue($index_number); | |||
$not_exact_match = PHPExcel_Calculation_Functions::flattenSingleValue($not_exact_match); | |||
// index_number must be greater than or equal to 1 | |||
if ($index_number < 1) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
// index_number must be less than or equal to the number of columns in lookup_array | |||
if ((!is_array($lookup_array)) || (empty($lookup_array))) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} else { | |||
$f = array_keys($lookup_array); | |||
$firstRow = array_pop($f); | |||
if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { | |||
return PHPExcel_Calculation_Functions::REF(); | |||
} else { | |||
$columnKeys = array_keys($lookup_array[$firstRow]); | |||
$firstkey = $f[0] - 1; | |||
$returnColumn = $firstkey + $index_number; | |||
$firstColumn = array_shift($f); | |||
} | |||
} | |||
if (!$not_exact_match) { | |||
$firstRowH = asort($lookup_array[$firstColumn]); | |||
} | |||
$rowNumber = $rowValue = false; | |||
foreach ($lookup_array[$firstColumn] as $rowKey => $rowData) { | |||
if ((is_numeric($lookup_value) && is_numeric($rowData) && ($rowData > $lookup_value)) || | |||
(!is_numeric($lookup_value) && !is_numeric($rowData) && (strtolower($rowData) > strtolower($lookup_value)))) { | |||
break; | |||
} | |||
$rowNumber = $rowKey; | |||
$rowValue = $rowData; | |||
} | |||
if ($rowNumber !== false) { | |||
if ((!$not_exact_match) && ($rowValue != $lookup_value)) { | |||
// if an exact match is required, we have what we need to return an appropriate response | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} else { | |||
// otherwise return the appropriate value | |||
return $lookup_array[$returnColumn][$rowNumber]; | |||
} | |||
} | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
/** | |||
* LOOKUP | |||
* The LOOKUP function searches for value either from a one-row or one-column range or from an array. | |||
* @param lookup_value The value that you want to match in lookup_array | |||
* @param lookup_vector The range of cells being searched | |||
* @param result_vector The column from which the matching value must be returned | |||
* @return mixed The value of the found cell | |||
*/ | |||
public static function LOOKUP($lookup_value, $lookup_vector, $result_vector = null) | |||
{ | |||
$lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); | |||
if (!is_array($lookup_vector)) { | |||
return PHPExcel_Calculation_Functions::NA(); | |||
} | |||
$lookupRows = count($lookup_vector); | |||
$l = array_keys($lookup_vector); | |||
$l = array_shift($l); | |||
$lookupColumns = count($lookup_vector[$l]); | |||
if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) { | |||
$lookup_vector = self::TRANSPOSE($lookup_vector); | |||
$lookupRows = count($lookup_vector); | |||
$l = array_keys($lookup_vector); | |||
$lookupColumns = count($lookup_vector[array_shift($l)]); | |||
} | |||
if (is_null($result_vector)) { | |||
$result_vector = $lookup_vector; | |||
} | |||
$resultRows = count($result_vector); | |||
$l = array_keys($result_vector); | |||
$l = array_shift($l); | |||
$resultColumns = count($result_vector[$l]); | |||
if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) { | |||
$result_vector = self::TRANSPOSE($result_vector); | |||
$resultRows = count($result_vector); | |||
$r = array_keys($result_vector); | |||
$resultColumns = count($result_vector[array_shift($r)]); | |||
} | |||
if ($lookupRows == 2) { | |||
$result_vector = array_pop($lookup_vector); | |||
$lookup_vector = array_shift($lookup_vector); | |||
} | |||
if ($lookupColumns != 2) { | |||
foreach ($lookup_vector as &$value) { | |||
if (is_array($value)) { | |||
$k = array_keys($value); | |||
$key1 = $key2 = array_shift($k); | |||
$key2++; | |||
$dataValue1 = $value[$key1]; | |||
} else { | |||
$key1 = 0; | |||
$key2 = 1; | |||
$dataValue1 = $value; | |||
} | |||
$dataValue2 = array_shift($result_vector); | |||
if (is_array($dataValue2)) { | |||
$dataValue2 = array_shift($dataValue2); | |||
} | |||
$value = array($key1 => $dataValue1, $key2 => $dataValue2); | |||
} | |||
unset($value); | |||
} | |||
return self::VLOOKUP($lookup_value, $lookup_vector, 2); | |||
} | |||
} |
@ -0,0 +1,651 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Calculation_TextData | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_TextData | |||
{ | |||
private static $invalidChars; | |||
private static function unicodeToOrd($c) | |||
{ | |||
if (ord($c{0}) >=0 && ord($c{0}) <= 127) { | |||
return ord($c{0}); | |||
} elseif (ord($c{0}) >= 192 && ord($c{0}) <= 223) { | |||
return (ord($c{0})-192)*64 + (ord($c{1})-128); | |||
} elseif (ord($c{0}) >= 224 && ord($c{0}) <= 239) { | |||
return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); | |||
} elseif (ord($c{0}) >= 240 && ord($c{0}) <= 247) { | |||
return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); | |||
} elseif (ord($c{0}) >= 248 && ord($c{0}) <= 251) { | |||
return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); | |||
} elseif (ord($c{0}) >= 252 && ord($c{0}) <= 253) { | |||
return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); | |||
} elseif (ord($c{0}) >= 254 && ord($c{0}) <= 255) { | |||
// error | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
return 0; | |||
} | |||
/** | |||
* CHARACTER | |||
* | |||
* @param string $character Value | |||
* @return int | |||
*/ | |||
public static function CHARACTER($character) | |||
{ | |||
$character = PHPExcel_Calculation_Functions::flattenSingleValue($character); | |||
if ((!is_numeric($character)) || ($character < 0)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (function_exists('mb_convert_encoding')) { | |||
return mb_convert_encoding('&#'.intval($character).';', 'UTF-8', 'HTML-ENTITIES'); | |||
} else { | |||
return chr(intval($character)); | |||
} | |||
} | |||
/** | |||
* TRIMNONPRINTABLE | |||
* | |||
* @param mixed $stringValue Value to check | |||
* @return string | |||
*/ | |||
public static function TRIMNONPRINTABLE($stringValue = '') | |||
{ | |||
$stringValue = PHPExcel_Calculation_Functions::flattenSingleValue($stringValue); | |||
if (is_bool($stringValue)) { | |||
return ($stringValue) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (self::$invalidChars == null) { | |||
self::$invalidChars = range(chr(0), chr(31)); | |||
} | |||
if (is_string($stringValue) || is_numeric($stringValue)) { | |||
return str_replace(self::$invalidChars, '', trim($stringValue, "\x00..\x1F")); | |||
} | |||
return null; | |||
} | |||
/** | |||
* TRIMSPACES | |||
* | |||
* @param mixed $stringValue Value to check | |||
* @return string | |||
*/ | |||
public static function TRIMSPACES($stringValue = '') | |||
{ | |||
$stringValue = PHPExcel_Calculation_Functions::flattenSingleValue($stringValue); | |||
if (is_bool($stringValue)) { | |||
return ($stringValue) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (is_string($stringValue) || is_numeric($stringValue)) { | |||
return trim(preg_replace('/ +/', ' ', trim($stringValue, ' ')), ' '); | |||
} | |||
return null; | |||
} | |||
/** | |||
* ASCIICODE | |||
* | |||
* @param string $characters Value | |||
* @return int | |||
*/ | |||
public static function ASCIICODE($characters) | |||
{ | |||
if (($characters === null) || ($characters === '')) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
$characters = PHPExcel_Calculation_Functions::flattenSingleValue($characters); | |||
if (is_bool($characters)) { | |||
if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { | |||
$characters = (int) $characters; | |||
} else { | |||
$characters = ($characters) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
} | |||
$character = $characters; | |||
if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { | |||
if (mb_strlen($characters, 'UTF-8') > 1) { | |||
$character = mb_substr($characters, 0, 1, 'UTF-8'); | |||
} | |||
return self::unicodeToOrd($character); | |||
} else { | |||
if (strlen($characters) > 0) { | |||
$character = substr($characters, 0, 1); | |||
} | |||
return ord($character); | |||
} | |||
} | |||
/** | |||
* CONCATENATE | |||
* | |||
* @return string | |||
*/ | |||
public static function CONCATENATE() | |||
{ | |||
$returnValue = ''; | |||
// Loop through arguments | |||
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); | |||
foreach ($aArgs as $arg) { | |||
if (is_bool($arg)) { | |||
if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { | |||
$arg = (int) $arg; | |||
} else { | |||
$arg = ($arg) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
} | |||
$returnValue .= $arg; | |||
} | |||
return $returnValue; | |||
} | |||
/** | |||
* DOLLAR | |||
* | |||
* This function converts a number to text using currency format, with the decimals rounded to the specified place. | |||
* The format used is $#,##0.00_);($#,##0.00).. | |||
* | |||
* @param float $value The value to format | |||
* @param int $decimals The number of digits to display to the right of the decimal point. | |||
* If decimals is negative, number is rounded to the left of the decimal point. | |||
* If you omit decimals, it is assumed to be 2 | |||
* @return string | |||
*/ | |||
public static function DOLLAR($value = 0, $decimals = 2) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$decimals = is_null($decimals) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($decimals); | |||
// Validate parameters | |||
if (!is_numeric($value) || !is_numeric($decimals)) { | |||
return PHPExcel_Calculation_Functions::NaN(); | |||
} | |||
$decimals = floor($decimals); | |||
$mask = '$#,##0'; | |||
if ($decimals > 0) { | |||
$mask .= '.' . str_repeat('0', $decimals); | |||
} else { | |||
$round = pow(10, abs($decimals)); | |||
if ($value < 0) { | |||
$round = 0-$round; | |||
} | |||
$value = PHPExcel_Calculation_MathTrig::MROUND($value, $round); | |||
} | |||
return PHPExcel_Style_NumberFormat::toFormattedString($value, $mask); | |||
} | |||
/** | |||
* SEARCHSENSITIVE | |||
* | |||
* @param string $needle The string to look for | |||
* @param string $haystack The string in which to look | |||
* @param int $offset Offset within $haystack | |||
* @return string | |||
*/ | |||
public static function SEARCHSENSITIVE($needle, $haystack, $offset = 1) | |||
{ | |||
$needle = PHPExcel_Calculation_Functions::flattenSingleValue($needle); | |||
$haystack = PHPExcel_Calculation_Functions::flattenSingleValue($haystack); | |||
$offset = PHPExcel_Calculation_Functions::flattenSingleValue($offset); | |||
if (!is_bool($needle)) { | |||
if (is_bool($haystack)) { | |||
$haystack = ($haystack) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (($offset > 0) && (PHPExcel_Shared_String::CountCharacters($haystack) > $offset)) { | |||
if (PHPExcel_Shared_String::CountCharacters($needle) == 0) { | |||
return $offset; | |||
} | |||
if (function_exists('mb_strpos')) { | |||
$pos = mb_strpos($haystack, $needle, --$offset, 'UTF-8'); | |||
} else { | |||
$pos = strpos($haystack, $needle, --$offset); | |||
} | |||
if ($pos !== false) { | |||
return ++$pos; | |||
} | |||
} | |||
} | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
/** | |||
* SEARCHINSENSITIVE | |||
* | |||
* @param string $needle The string to look for | |||
* @param string $haystack The string in which to look | |||
* @param int $offset Offset within $haystack | |||
* @return string | |||
*/ | |||
public static function SEARCHINSENSITIVE($needle, $haystack, $offset = 1) | |||
{ | |||
$needle = PHPExcel_Calculation_Functions::flattenSingleValue($needle); | |||
$haystack = PHPExcel_Calculation_Functions::flattenSingleValue($haystack); | |||
$offset = PHPExcel_Calculation_Functions::flattenSingleValue($offset); | |||
if (!is_bool($needle)) { | |||
if (is_bool($haystack)) { | |||
$haystack = ($haystack) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (($offset > 0) && (PHPExcel_Shared_String::CountCharacters($haystack) > $offset)) { | |||
if (PHPExcel_Shared_String::CountCharacters($needle) == 0) { | |||
return $offset; | |||
} | |||
if (function_exists('mb_stripos')) { | |||
$pos = mb_stripos($haystack, $needle, --$offset, 'UTF-8'); | |||
} else { | |||
$pos = stripos($haystack, $needle, --$offset); | |||
} | |||
if ($pos !== false) { | |||
return ++$pos; | |||
} | |||
} | |||
} | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
/** | |||
* FIXEDFORMAT | |||
* | |||
* @param mixed $value Value to check | |||
* @param integer $decimals | |||
* @param boolean $no_commas | |||
* @return boolean | |||
*/ | |||
public static function FIXEDFORMAT($value, $decimals = 2, $no_commas = false) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$decimals = PHPExcel_Calculation_Functions::flattenSingleValue($decimals); | |||
$no_commas = PHPExcel_Calculation_Functions::flattenSingleValue($no_commas); | |||
// Validate parameters | |||
if (!is_numeric($value) || !is_numeric($decimals)) { | |||
return PHPExcel_Calculation_Functions::NaN(); | |||
} | |||
$decimals = floor($decimals); | |||
$valueResult = round($value, $decimals); | |||
if ($decimals < 0) { | |||
$decimals = 0; | |||
} | |||
if (!$no_commas) { | |||
$valueResult = number_format($valueResult, $decimals); | |||
} | |||
return (string) $valueResult; | |||
} | |||
/** | |||
* LEFT | |||
* | |||
* @param string $value Value | |||
* @param int $chars Number of characters | |||
* @return string | |||
*/ | |||
public static function LEFT($value = '', $chars = 1) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
if ($chars < 0) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (function_exists('mb_substr')) { | |||
return mb_substr($value, 0, $chars, 'UTF-8'); | |||
} else { | |||
return substr($value, 0, $chars); | |||
} | |||
} | |||
/** | |||
* MID | |||
* | |||
* @param string $value Value | |||
* @param int $start Start character | |||
* @param int $chars Number of characters | |||
* @return string | |||
*/ | |||
public static function MID($value = '', $start = 1, $chars = null) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$start = PHPExcel_Calculation_Functions::flattenSingleValue($start); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
if (($start < 1) || ($chars < 0)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (function_exists('mb_substr')) { | |||
return mb_substr($value, --$start, $chars, 'UTF-8'); | |||
} else { | |||
return substr($value, --$start, $chars); | |||
} | |||
} | |||
/** | |||
* RIGHT | |||
* | |||
* @param string $value Value | |||
* @param int $chars Number of characters | |||
* @return string | |||
*/ | |||
public static function RIGHT($value = '', $chars = 1) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
if ($chars < 0) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { | |||
return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); | |||
} else { | |||
return substr($value, strlen($value) - $chars); | |||
} | |||
} | |||
/** | |||
* STRINGLENGTH | |||
* | |||
* @param string $value Value | |||
* @return string | |||
*/ | |||
public static function STRINGLENGTH($value = '') | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (function_exists('mb_strlen')) { | |||
return mb_strlen($value, 'UTF-8'); | |||
} else { | |||
return strlen($value); | |||
} | |||
} | |||
/** | |||
* LOWERCASE | |||
* | |||
* Converts a string value to upper case. | |||
* | |||
* @param string $mixedCaseString | |||
* @return string | |||
*/ | |||
public static function LOWERCASE($mixedCaseString) | |||
{ | |||
$mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); | |||
if (is_bool($mixedCaseString)) { | |||
$mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
return PHPExcel_Shared_String::StrToLower($mixedCaseString); | |||
} | |||
/** | |||
* UPPERCASE | |||
* | |||
* Converts a string value to upper case. | |||
* | |||
* @param string $mixedCaseString | |||
* @return string | |||
*/ | |||
public static function UPPERCASE($mixedCaseString) | |||
{ | |||
$mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); | |||
if (is_bool($mixedCaseString)) { | |||
$mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
return PHPExcel_Shared_String::StrToUpper($mixedCaseString); | |||
} | |||
/** | |||
* PROPERCASE | |||
* | |||
* Converts a string value to upper case. | |||
* | |||
* @param string $mixedCaseString | |||
* @return string | |||
*/ | |||
public static function PROPERCASE($mixedCaseString) | |||
{ | |||
$mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); | |||
if (is_bool($mixedCaseString)) { | |||
$mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
return PHPExcel_Shared_String::StrToTitle($mixedCaseString); | |||
} | |||
/** | |||
* REPLACE | |||
* | |||
* @param string $oldText String to modify | |||
* @param int $start Start character | |||
* @param int $chars Number of characters | |||
* @param string $newText String to replace in defined position | |||
* @return string | |||
*/ | |||
public static function REPLACE($oldText = '', $start = 1, $chars = null, $newText) | |||
{ | |||
$oldText = PHPExcel_Calculation_Functions::flattenSingleValue($oldText); | |||
$start = PHPExcel_Calculation_Functions::flattenSingleValue($start); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
$newText = PHPExcel_Calculation_Functions::flattenSingleValue($newText); | |||
$left = self::LEFT($oldText, $start-1); | |||
$right = self::RIGHT($oldText, self::STRINGLENGTH($oldText)-($start+$chars)+1); | |||
return $left.$newText.$right; | |||
} | |||
/** | |||
* SUBSTITUTE | |||
* | |||
* @param string $text Value | |||
* @param string $fromText From Value | |||
* @param string $toText To Value | |||
* @param integer $instance Instance Number | |||
* @return string | |||
*/ | |||
public static function SUBSTITUTE($text = '', $fromText = '', $toText = '', $instance = 0) | |||
{ | |||
$text = PHPExcel_Calculation_Functions::flattenSingleValue($text); | |||
$fromText = PHPExcel_Calculation_Functions::flattenSingleValue($fromText); | |||
$toText = PHPExcel_Calculation_Functions::flattenSingleValue($toText); | |||
$instance = floor(PHPExcel_Calculation_Functions::flattenSingleValue($instance)); | |||
if ($instance == 0) { | |||
if (function_exists('mb_str_replace')) { | |||
return mb_str_replace($fromText, $toText, $text); | |||
} else { | |||
return str_replace($fromText, $toText, $text); | |||
} | |||
} else { | |||
$pos = -1; | |||
while ($instance > 0) { | |||
if (function_exists('mb_strpos')) { | |||
$pos = mb_strpos($text, $fromText, $pos+1, 'UTF-8'); | |||
} else { | |||
$pos = strpos($text, $fromText, $pos+1); | |||
} | |||
if ($pos === false) { | |||
break; | |||
} | |||
--$instance; | |||
} | |||
if ($pos !== false) { | |||
if (function_exists('mb_strlen')) { | |||
return self::REPLACE($text, ++$pos, mb_strlen($fromText, 'UTF-8'), $toText); | |||
} else { | |||
return self::REPLACE($text, ++$pos, strlen($fromText), $toText); | |||
} | |||
} | |||
} | |||
return $text; | |||
} | |||
/** | |||
* RETURNSTRING | |||
* | |||
* @param mixed $testValue Value to check | |||
* @return boolean | |||
*/ | |||
public static function RETURNSTRING($testValue = '') | |||
{ | |||
$testValue = PHPExcel_Calculation_Functions::flattenSingleValue($testValue); | |||
if (is_string($testValue)) { | |||
return $testValue; | |||
} | |||
return null; | |||
} | |||
/** | |||
* TEXTFORMAT | |||
* | |||
* @param mixed $value Value to check | |||
* @param string $format Format mask to use | |||
* @return boolean | |||
*/ | |||
public static function TEXTFORMAT($value, $format) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$format = PHPExcel_Calculation_Functions::flattenSingleValue($format); | |||
if ((is_string($value)) && (!is_numeric($value)) && PHPExcel_Shared_Date::isDateTimeFormatCode($format)) { | |||
$value = PHPExcel_Calculation_DateTime::DATEVALUE($value); | |||
} | |||
return (string) PHPExcel_Style_NumberFormat::toFormattedString($value, $format); | |||
} | |||
/** | |||
* VALUE | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function VALUE($value = '') | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
if (!is_numeric($value)) { | |||
$numberValue = str_replace( | |||
PHPExcel_Shared_String::getThousandsSeparator(), | |||
'', | |||
trim($value, " \t\n\r\0\x0B" . PHPExcel_Shared_String::getCurrencyCode()) | |||
); | |||
if (is_numeric($numberValue)) { | |||
return (float) $numberValue; | |||
} | |||
$dateSetting = PHPExcel_Calculation_Functions::getReturnDateType(); | |||
PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); | |||
if (strpos($value, ':') !== false) { | |||
$timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($value); | |||
if ($timeValue !== PHPExcel_Calculation_Functions::VALUE()) { | |||
PHPExcel_Calculation_Functions::setReturnDateType($dateSetting); | |||
return $timeValue; | |||
} | |||
} | |||
$dateValue = PHPExcel_Calculation_DateTime::DATEVALUE($value); | |||
if ($dateValue !== PHPExcel_Calculation_Functions::VALUE()) { | |||
PHPExcel_Calculation_Functions::setReturnDateType($dateSetting); | |||
return $dateValue; | |||
} | |||
PHPExcel_Calculation_Functions::setReturnDateType($dateSetting); | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
return (float) $value; | |||
} | |||
} |
@ -0,0 +1,651 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Calculation_TextData | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_TextData | |||
{ | |||
private static $invalidChars; | |||
private static function unicodeToOrd($c) | |||
{ | |||
if (ord($c{0}) >=0 && ord($c{0}) <= 127) { | |||
return ord($c{0}); | |||
} elseif (ord($c{0}) >= 192 && ord($c{0}) <= 223) { | |||
return (ord($c{0})-192)*64 + (ord($c{1})-128); | |||
} elseif (ord($c{0}) >= 224 && ord($c{0}) <= 239) { | |||
return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); | |||
} elseif (ord($c{0}) >= 240 && ord($c{0}) <= 247) { | |||
return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); | |||
} elseif (ord($c{0}) >= 248 && ord($c{0}) <= 251) { | |||
return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); | |||
} elseif (ord($c{0}) >= 252 && ord($c{0}) <= 253) { | |||
return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); | |||
} elseif (ord($c{0}) >= 254 && ord($c{0}) <= 255) { | |||
// error | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
return 0; | |||
} | |||
/** | |||
* CHARACTER | |||
* | |||
* @param string $character Value | |||
* @return int | |||
*/ | |||
public static function CHARACTER($character) | |||
{ | |||
$character = PHPExcel_Calculation_Functions::flattenSingleValue($character); | |||
if ((!is_numeric($character)) || ($character < 0)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (function_exists('mb_convert_encoding')) { | |||
return mb_convert_encoding('&#'.intval($character).';', 'UTF-8', 'HTML-ENTITIES'); | |||
} else { | |||
return chr(intval($character)); | |||
} | |||
} | |||
/** | |||
* TRIMNONPRINTABLE | |||
* | |||
* @param mixed $stringValue Value to check | |||
* @return string | |||
*/ | |||
public static function TRIMNONPRINTABLE($stringValue = '') | |||
{ | |||
$stringValue = PHPExcel_Calculation_Functions::flattenSingleValue($stringValue); | |||
if (is_bool($stringValue)) { | |||
return ($stringValue) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (self::$invalidChars == null) { | |||
self::$invalidChars = range(chr(0), chr(31)); | |||
} | |||
if (is_string($stringValue) || is_numeric($stringValue)) { | |||
return str_replace(self::$invalidChars, '', trim($stringValue, "\x00..\x1F")); | |||
} | |||
return null; | |||
} | |||
/** | |||
* TRIMSPACES | |||
* | |||
* @param mixed $stringValue Value to check | |||
* @return string | |||
*/ | |||
public static function TRIMSPACES($stringValue = '') | |||
{ | |||
$stringValue = PHPExcel_Calculation_Functions::flattenSingleValue($stringValue); | |||
if (is_bool($stringValue)) { | |||
return ($stringValue) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (is_string($stringValue) || is_numeric($stringValue)) { | |||
return trim(preg_replace('/ +/', ' ', trim($stringValue, ' ')), ' '); | |||
} | |||
return null; | |||
} | |||
/** | |||
* ASCIICODE | |||
* | |||
* @param string $characters Value | |||
* @return int | |||
*/ | |||
public static function ASCIICODE($characters) | |||
{ | |||
if (($characters === null) || ($characters === '')) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
$characters = PHPExcel_Calculation_Functions::flattenSingleValue($characters); | |||
if (is_bool($characters)) { | |||
if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { | |||
$characters = (int) $characters; | |||
} else { | |||
$characters = ($characters) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
} | |||
$character = $characters; | |||
if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { | |||
if (mb_strlen($characters, 'UTF-8') > 1) { | |||
$character = mb_substr($characters, 0, 1, 'UTF-8'); | |||
} | |||
return self::unicodeToOrd($character); | |||
} else { | |||
if (strlen($characters) > 0) { | |||
$character = substr($characters, 0, 1); | |||
} | |||
return ord($character); | |||
} | |||
} | |||
/** | |||
* CONCATENATE | |||
* | |||
* @return string | |||
*/ | |||
public static function CONCATENATE() | |||
{ | |||
$returnValue = ''; | |||
// Loop through arguments | |||
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); | |||
foreach ($aArgs as $arg) { | |||
if (is_bool($arg)) { | |||
if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { | |||
$arg = (int) $arg; | |||
} else { | |||
$arg = ($arg) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
} | |||
$returnValue .= $arg; | |||
} | |||
return $returnValue; | |||
} | |||
/** | |||
* DOLLAR | |||
* | |||
* This function converts a number to text using currency format, with the decimals rounded to the specified place. | |||
* The format used is $#,##0.00_);($#,##0.00).. | |||
* | |||
* @param float $value The value to format | |||
* @param int $decimals The number of digits to display to the right of the decimal point. | |||
* If decimals is negative, number is rounded to the left of the decimal point. | |||
* If you omit decimals, it is assumed to be 2 | |||
* @return string | |||
*/ | |||
public static function DOLLAR($value = 0, $decimals = 2) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$decimals = is_null($decimals) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($decimals); | |||
// Validate parameters | |||
if (!is_numeric($value) || !is_numeric($decimals)) { | |||
return PHPExcel_Calculation_Functions::NaN(); | |||
} | |||
$decimals = floor($decimals); | |||
$mask = '$#,##0'; | |||
if ($decimals > 0) { | |||
$mask .= '.' . str_repeat('0', $decimals); | |||
} else { | |||
$round = pow(10, abs($decimals)); | |||
if ($value < 0) { | |||
$round = 0-$round; | |||
} | |||
$value = PHPExcel_Calculation_MathTrig::MROUND($value, $round); | |||
} | |||
return PHPExcel_Style_NumberFormat::toFormattedString($value, $mask); | |||
} | |||
/** | |||
* SEARCHSENSITIVE | |||
* | |||
* @param string $needle The string to look for | |||
* @param string $haystack The string in which to look | |||
* @param int $offset Offset within $haystack | |||
* @return string | |||
*/ | |||
public static function SEARCHSENSITIVE($needle, $haystack, $offset = 1) | |||
{ | |||
$needle = PHPExcel_Calculation_Functions::flattenSingleValue($needle); | |||
$haystack = PHPExcel_Calculation_Functions::flattenSingleValue($haystack); | |||
$offset = PHPExcel_Calculation_Functions::flattenSingleValue($offset); | |||
if (!is_bool($needle)) { | |||
if (is_bool($haystack)) { | |||
$haystack = ($haystack) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (($offset > 0) && (PHPExcel_Shared_String::CountCharacters($haystack) > $offset)) { | |||
if (PHPExcel_Shared_String::CountCharacters($needle) == 0) { | |||
return $offset; | |||
} | |||
if (function_exists('mb_strpos')) { | |||
$pos = mb_strpos($haystack, $needle, --$offset, 'UTF-8'); | |||
} else { | |||
$pos = strpos($haystack, $needle, --$offset); | |||
} | |||
if ($pos !== false) { | |||
return ++$pos; | |||
} | |||
} | |||
} | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
/** | |||
* SEARCHINSENSITIVE | |||
* | |||
* @param string $needle The string to look for | |||
* @param string $haystack The string in which to look | |||
* @param int $offset Offset within $haystack | |||
* @return string | |||
*/ | |||
public static function SEARCHINSENSITIVE($needle, $haystack, $offset = 1) | |||
{ | |||
$needle = PHPExcel_Calculation_Functions::flattenSingleValue($needle); | |||
$haystack = PHPExcel_Calculation_Functions::flattenSingleValue($haystack); | |||
$offset = PHPExcel_Calculation_Functions::flattenSingleValue($offset); | |||
if (!is_bool($needle)) { | |||
if (is_bool($haystack)) { | |||
$haystack = ($haystack) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (($offset > 0) && (PHPExcel_Shared_String::CountCharacters($haystack) > $offset)) { | |||
if (PHPExcel_Shared_String::CountCharacters($needle) == 0) { | |||
return $offset; | |||
} | |||
if (function_exists('mb_stripos')) { | |||
$pos = mb_stripos($haystack, $needle, --$offset, 'UTF-8'); | |||
} else { | |||
$pos = stripos($haystack, $needle, --$offset); | |||
} | |||
if ($pos !== false) { | |||
return ++$pos; | |||
} | |||
} | |||
} | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
/** | |||
* FIXEDFORMAT | |||
* | |||
* @param mixed $value Value to check | |||
* @param integer $decimals | |||
* @param boolean $no_commas | |||
* @return boolean | |||
*/ | |||
public static function FIXEDFORMAT($value, $decimals = 2, $no_commas = false) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$decimals = PHPExcel_Calculation_Functions::flattenSingleValue($decimals); | |||
$no_commas = PHPExcel_Calculation_Functions::flattenSingleValue($no_commas); | |||
// Validate parameters | |||
if (!is_numeric($value) || !is_numeric($decimals)) { | |||
return PHPExcel_Calculation_Functions::NaN(); | |||
} | |||
$decimals = floor($decimals); | |||
$valueResult = round($value, $decimals); | |||
if ($decimals < 0) { | |||
$decimals = 0; | |||
} | |||
if (!$no_commas) { | |||
$valueResult = number_format($valueResult, $decimals); | |||
} | |||
return (string) $valueResult; | |||
} | |||
/** | |||
* LEFT | |||
* | |||
* @param string $value Value | |||
* @param int $chars Number of characters | |||
* @return string | |||
*/ | |||
public static function LEFT($value = '', $chars = 1) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
if ($chars < 0) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (function_exists('mb_substr')) { | |||
return mb_substr($value, 0, $chars, 'UTF-8'); | |||
} else { | |||
return substr($value, 0, $chars); | |||
} | |||
} | |||
/** | |||
* MID | |||
* | |||
* @param string $value Value | |||
* @param int $start Start character | |||
* @param int $chars Number of characters | |||
* @return string | |||
*/ | |||
public static function MID($value = '', $start = 1, $chars = null) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$start = PHPExcel_Calculation_Functions::flattenSingleValue($start); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
if (($start < 1) || ($chars < 0)) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (function_exists('mb_substr')) { | |||
return mb_substr($value, --$start, $chars, 'UTF-8'); | |||
} else { | |||
return substr($value, --$start, $chars); | |||
} | |||
} | |||
/** | |||
* RIGHT | |||
* | |||
* @param string $value Value | |||
* @param int $chars Number of characters | |||
* @return string | |||
*/ | |||
public static function RIGHT($value = '', $chars = 1) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
if ($chars < 0) { | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { | |||
return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); | |||
} else { | |||
return substr($value, strlen($value) - $chars); | |||
} | |||
} | |||
/** | |||
* STRINGLENGTH | |||
* | |||
* @param string $value Value | |||
* @return string | |||
*/ | |||
public static function STRINGLENGTH($value = '') | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
if (is_bool($value)) { | |||
$value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
if (function_exists('mb_strlen')) { | |||
return mb_strlen($value, 'UTF-8'); | |||
} else { | |||
return strlen($value); | |||
} | |||
} | |||
/** | |||
* LOWERCASE | |||
* | |||
* Converts a string value to upper case. | |||
* | |||
* @param string $mixedCaseString | |||
* @return string | |||
*/ | |||
public static function LOWERCASE($mixedCaseString) | |||
{ | |||
$mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); | |||
if (is_bool($mixedCaseString)) { | |||
$mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
return PHPExcel_Shared_String::StrToLower($mixedCaseString); | |||
} | |||
/** | |||
* UPPERCASE | |||
* | |||
* Converts a string value to upper case. | |||
* | |||
* @param string $mixedCaseString | |||
* @return string | |||
*/ | |||
public static function UPPERCASE($mixedCaseString) | |||
{ | |||
$mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); | |||
if (is_bool($mixedCaseString)) { | |||
$mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
return PHPExcel_Shared_String::StrToUpper($mixedCaseString); | |||
} | |||
/** | |||
* PROPERCASE | |||
* | |||
* Converts a string value to upper case. | |||
* | |||
* @param string $mixedCaseString | |||
* @return string | |||
*/ | |||
public static function PROPERCASE($mixedCaseString) | |||
{ | |||
$mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); | |||
if (is_bool($mixedCaseString)) { | |||
$mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); | |||
} | |||
return PHPExcel_Shared_String::StrToTitle($mixedCaseString); | |||
} | |||
/** | |||
* REPLACE | |||
* | |||
* @param string $oldText String to modify | |||
* @param int $start Start character | |||
* @param int $chars Number of characters | |||
* @param string $newText String to replace in defined position | |||
* @return string | |||
*/ | |||
public static function REPLACE($oldText = '', $start = 1, $chars = null, $newText) | |||
{ | |||
$oldText = PHPExcel_Calculation_Functions::flattenSingleValue($oldText); | |||
$start = PHPExcel_Calculation_Functions::flattenSingleValue($start); | |||
$chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); | |||
$newText = PHPExcel_Calculation_Functions::flattenSingleValue($newText); | |||
$left = self::LEFT($oldText, $start-1); | |||
$right = self::RIGHT($oldText, self::STRINGLENGTH($oldText)-($start+$chars)+1); | |||
return $left.$newText.$right; | |||
} | |||
/** | |||
* SUBSTITUTE | |||
* | |||
* @param string $text Value | |||
* @param string $fromText From Value | |||
* @param string $toText To Value | |||
* @param integer $instance Instance Number | |||
* @return string | |||
*/ | |||
public static function SUBSTITUTE($text = '', $fromText = '', $toText = '', $instance = 0) | |||
{ | |||
$text = PHPExcel_Calculation_Functions::flattenSingleValue($text); | |||
$fromText = PHPExcel_Calculation_Functions::flattenSingleValue($fromText); | |||
$toText = PHPExcel_Calculation_Functions::flattenSingleValue($toText); | |||
$instance = floor(PHPExcel_Calculation_Functions::flattenSingleValue($instance)); | |||
if ($instance == 0) { | |||
if (function_exists('mb_str_replace')) { | |||
return mb_str_replace($fromText, $toText, $text); | |||
} else { | |||
return str_replace($fromText, $toText, $text); | |||
} | |||
} else { | |||
$pos = -1; | |||
while ($instance > 0) { | |||
if (function_exists('mb_strpos')) { | |||
$pos = mb_strpos($text, $fromText, $pos+1, 'UTF-8'); | |||
} else { | |||
$pos = strpos($text, $fromText, $pos+1); | |||
} | |||
if ($pos === false) { | |||
break; | |||
} | |||
--$instance; | |||
} | |||
if ($pos !== false) { | |||
if (function_exists('mb_strlen')) { | |||
return self::REPLACE($text, ++$pos, mb_strlen($fromText, 'UTF-8'), $toText); | |||
} else { | |||
return self::REPLACE($text, ++$pos, strlen($fromText), $toText); | |||
} | |||
} | |||
} | |||
return $text; | |||
} | |||
/** | |||
* RETURNSTRING | |||
* | |||
* @param mixed $testValue Value to check | |||
* @return boolean | |||
*/ | |||
public static function RETURNSTRING($testValue = '') | |||
{ | |||
$testValue = PHPExcel_Calculation_Functions::flattenSingleValue($testValue); | |||
if (is_string($testValue)) { | |||
return $testValue; | |||
} | |||
return null; | |||
} | |||
/** | |||
* TEXTFORMAT | |||
* | |||
* @param mixed $value Value to check | |||
* @param string $format Format mask to use | |||
* @return boolean | |||
*/ | |||
public static function TEXTFORMAT($value, $format) | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
$format = PHPExcel_Calculation_Functions::flattenSingleValue($format); | |||
if ((is_string($value)) && (!is_numeric($value)) && PHPExcel_Shared_Date::isDateTimeFormatCode($format)) { | |||
$value = PHPExcel_Calculation_DateTime::DATEVALUE($value); | |||
} | |||
return (string) PHPExcel_Style_NumberFormat::toFormattedString($value, $format); | |||
} | |||
/** | |||
* VALUE | |||
* | |||
* @param mixed $value Value to check | |||
* @return boolean | |||
*/ | |||
public static function VALUE($value = '') | |||
{ | |||
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value); | |||
if (!is_numeric($value)) { | |||
$numberValue = str_replace( | |||
PHPExcel_Shared_String::getThousandsSeparator(), | |||
'', | |||
trim($value, " \t\n\r\0\x0B" . PHPExcel_Shared_String::getCurrencyCode()) | |||
); | |||
if (is_numeric($numberValue)) { | |||
return (float) $numberValue; | |||
} | |||
$dateSetting = PHPExcel_Calculation_Functions::getReturnDateType(); | |||
PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); | |||
if (strpos($value, ':') !== false) { | |||
$timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($value); | |||
if ($timeValue !== PHPExcel_Calculation_Functions::VALUE()) { | |||
PHPExcel_Calculation_Functions::setReturnDateType($dateSetting); | |||
return $timeValue; | |||
} | |||
} | |||
$dateValue = PHPExcel_Calculation_DateTime::DATEVALUE($value); | |||
if ($dateValue !== PHPExcel_Calculation_Functions::VALUE()) { | |||
PHPExcel_Calculation_Functions::setReturnDateType($dateSetting); | |||
return $dateValue; | |||
} | |||
PHPExcel_Calculation_Functions::setReturnDateType($dateSetting); | |||
return PHPExcel_Calculation_Functions::VALUE(); | |||
} | |||
return (float) $value; | |||
} | |||
} |
@ -0,0 +1,111 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Calculation_Token_Stack | |||
* | |||
* Copyright (c) 2006 - 2015 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_Calculation | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Calculation_Token_Stack | |||
{ | |||
/** | |||
* The parser stack for formulae | |||
* | |||
* @var mixed[] | |||
*/ | |||
private $stack = array(); | |||
/** | |||
* Count of entries in the parser stack | |||
* | |||
* @var integer | |||
*/ | |||
private $count = 0; | |||
/** | |||
* Return the number of entries on the stack | |||
* | |||
* @return integer | |||
*/ | |||
public function count() | |||
{ | |||
return $this->count; | |||
} | |||
/** | |||
* Push a new entry onto the stack | |||
* | |||
* @param mixed $type | |||
* @param mixed $value | |||
* @param mixed $reference | |||
*/ | |||
public function push($type, $value, $reference = null) | |||
{ | |||
$this->stack[$this->count++] = array( | |||
'type' => $type, | |||
'value' => $value, | |||
'reference' => $reference | |||
); | |||
if ($type == 'Function') { | |||
$localeFunction = PHPExcel_Calculation::localeFunc($value); | |||
if ($localeFunction != $value) { | |||
$this->stack[($this->count - 1)]['localeValue'] = $localeFunction; | |||
} | |||
} | |||
} | |||
/** | |||
* Pop the last entry from the stack | |||
* | |||
* @return mixed | |||
*/ | |||
public function pop() | |||
{ | |||
if ($this->count > 0) { | |||
return $this->stack[--$this->count]; | |||
} | |||
return null; | |||
} | |||
/** | |||
* Return an entry from the stack without removing it | |||
* | |||
* @param integer $n number indicating how far back in the stack we want to look | |||
* @return mixed | |||
*/ | |||
public function last($n = 1) | |||
{ | |||
if ($this->count - $n < 0) { | |||
return null; | |||
} | |||
return $this->stack[$this->count - $n]; | |||
} | |||
/** | |||
* Clear the stack | |||
*/ | |||
public function clear() | |||
{ | |||
$this->stack = array(); | |||
$this->count = 0; | |||
} | |||
} |
@ -0,0 +1,351 @@ | |||
ABS | |||
ACCRINT | |||
ACCRINTM | |||
ACOS | |||
ACOSH | |||
ADDRESS | |||
AMORDEGRC | |||
AMORLINC | |||
AND | |||
AREAS | |||
ASC | |||
ASIN | |||
ASINH | |||
ATAN | |||
ATAN2 | |||
ATANH | |||
AVEDEV | |||
AVERAGE | |||
AVERAGEA | |||
AVERAGEIF | |||
AVERAGEIFS | |||
BAHTTEXT | |||
BESSELI | |||
BESSELJ | |||
BESSELK | |||
BESSELY | |||
BETADIST | |||
BETAINV | |||
BIN2DEC | |||
BIN2HEX | |||
BIN2OCT | |||
BINOMDIST | |||
CEILING | |||
CELL | |||
CHAR | |||
CHIDIST | |||
CHIINV | |||
CHITEST | |||
CHOOSE | |||
CLEAN | |||
CODE | |||
COLUMN | |||
COLUMNS | |||
COMBIN | |||
COMPLEX | |||
CONCATENATE | |||
CONFIDENCE | |||
CONVERT | |||
CORREL | |||
COS | |||
COSH | |||
COUNT | |||
COUNTA | |||
COUNTBLANK | |||
COUNTIF | |||
COUNTIFS | |||
COUPDAYBS | |||
COUPDAYBS | |||
COUPDAYSNC | |||
COUPNCD | |||
COUPNUM | |||
COUPPCD | |||
COVAR | |||
CRITBINOM | |||
CUBEKPIMEMBER | |||
CUBEMEMBER | |||
CUBEMEMBERPROPERTY | |||
CUBERANKEDMEMBER | |||
CUBESET | |||
CUBESETCOUNT | |||
CUBEVALUE | |||
CUMIPMT | |||
CUMPRINC | |||
DATE | |||
DATEDIF | |||
DATEVALUE | |||
DAVERAGE | |||
DAY | |||
DAYS360 | |||
DB | |||
DCOUNT | |||
DCOUNTA | |||
DDB | |||
DEC2BIN | |||
DEC2HEX | |||
DEC2OCT | |||
DEGREES | |||
DELTA | |||
DEVSQ | |||
DGET | |||
DISC | |||
DMAX | |||
DMIN | |||
DOLLAR | |||
DOLLARDE | |||
DOLLARFR | |||
DPRODUCT | |||
DSTDEV | |||
DSTDEVP | |||
DSUM | |||
DURATION | |||
DVAR | |||
DVARP | |||
EDATE | |||
EFFECT | |||
EOMONTH | |||
ERF | |||
ERFC | |||
ERROR.TYPE | |||
EVEN | |||
EXACT | |||
EXP | |||
EXPONDIST | |||
FACT | |||
FACTDOUBLE | |||
FALSE | |||
FDIST | |||
FIND | |||
FINDB | |||
FINV | |||
FISHER | |||
FISHERINV | |||
FIXED | |||
FLOOR | |||
FORECAST | |||
FREQUENCY | |||
FTEST | |||
FV | |||
FVSCHEDULE | |||
GAMAMDIST | |||
GAMMAINV | |||
GAMMALN | |||
GCD | |||
GEOMEAN | |||
GESTEP | |||
GETPIVOTDATA | |||
GROWTH | |||
HARMEAN | |||
HEX2BIN | |||
HEX2OCT | |||
HLOOKUP | |||
HOUR | |||
HYPERLINK | |||
HYPGEOMDIST | |||
IF | |||
IFERROR | |||
IMABS | |||
IMAGINARY | |||
IMARGUMENT | |||
IMCONJUGATE | |||
IMCOS | |||
IMEXP | |||
IMLN | |||
IMLOG10 | |||
IMLOG2 | |||
IMPOWER | |||
IMPRODUCT | |||
IMREAL | |||
IMSIN | |||
IMSQRT | |||
IMSUB | |||
IMSUM | |||
INDEX | |||
INDIRECT | |||
INFO | |||
INT | |||
INTERCEPT | |||
INTRATE | |||
IPMT | |||
IRR | |||
ISBLANK | |||
ISERR | |||
ISERROR | |||
ISEVEN | |||
ISLOGICAL | |||
ISNA | |||
ISNONTEXT | |||
ISNUMBER | |||
ISODD | |||
ISPMT | |||
ISREF | |||
ISTEXT | |||
JIS | |||
KURT | |||
LARGE | |||
LCM | |||
LEFT | |||
LEFTB | |||
LEN | |||
LENB | |||
LINEST | |||
LN | |||
LOG | |||
LOG10 | |||
LOGEST | |||
LOGINV | |||
LOGNORMDIST | |||
LOOKUP | |||
LOWER | |||
MATCH | |||
MAX | |||
MAXA | |||
MDETERM | |||
MDURATION | |||
MEDIAN | |||
MID | |||
MIDB | |||
MIN | |||
MINA | |||
MINUTE | |||
MINVERSE | |||
MIRR | |||
MMULT | |||
MOD | |||
MODE | |||
MONTH | |||
MROUND | |||
MULTINOMIAL | |||
N | |||
NA | |||
NEGBINOMDIST | |||
NETWORKDAYS | |||
NOMINAL | |||
NORMDIST | |||
NORMINV | |||
NORMSDIST | |||
NORMSINV | |||
NOT | |||
NOW | |||
NPER | |||
NPV | |||
OCT2BIN | |||
OCT2DEC | |||
OCT2HEX | |||
ODD | |||
ODDFPRICE | |||
ODDFYIELD | |||
ODDLPRICE | |||
ODDLYIELD | |||
OFFSET | |||
OR | |||
PEARSON | |||
PERCENTILE | |||
PERCENTRANK | |||
PERMUT | |||
PHONETIC | |||
PI | |||
PMT | |||
POISSON | |||
POWER | |||
PPMT | |||
PRICE | |||
PRICEDISC | |||
PRICEMAT | |||
PROB | |||
PRODUCT | |||
PROPER | |||
PV | |||
QUARTILE | |||
QUOTIENT | |||
RADIANS | |||
RAND | |||
RANDBETWEEN | |||
RANK | |||
RATE | |||
RECEIVED | |||
REPLACE | |||
REPLACEB | |||
REPT | |||
RIGHT | |||
RIGHTB | |||
ROMAN | |||
ROUND | |||
ROUNDDOWN | |||
ROUNDUP | |||
ROW | |||
ROWS | |||
RSQ | |||
RTD | |||
SEARCH | |||
SEARCHB | |||
SECOND | |||
SERIESSUM | |||
SIGN | |||
SIN | |||
SINH | |||
SKEW | |||
SLN | |||
SLOPE | |||
SMALL | |||
SQRT | |||
SQRTPI | |||
STANDARDIZE | |||
STDEV | |||
STDEVA | |||
STDEVP | |||
STDEVPA | |||
STEYX | |||
SUBSTITUTE | |||
SUBTOTAL | |||
SUM | |||
SUMIF | |||
SUMIFS | |||
SUMPRODUCT | |||
SUMSQ | |||
SUMX2MY2 | |||
SUMX2PY2 | |||
SUMXMY2 | |||
SYD | |||
T | |||
TAN | |||
TANH | |||
TBILLEQ | |||
TBILLPRICE | |||
TBILLYIELD | |||
TDIST | |||
TEXT | |||
TIME | |||
TIMEVALUE | |||
TINV | |||
TODAY | |||
TRANSPOSE | |||
TREND | |||
TRIM | |||
TRIMMEAN | |||
TRUE | |||
TRUNC | |||
TTEST | |||
TYPE | |||
UPPER | |||
USDOLLAR | |||
VALUE | |||
VAR | |||
VARA | |||
VARP | |||
VARPA | |||
VDB | |||
VERSION | |||
VLOOKUP | |||
WEEKDAY | |||
WEEKNUM | |||
WEIBULL | |||
WORKDAY | |||
XIRR | |||
XNPV | |||
YEAR | |||
YEARFRAC | |||
YIELD | |||
YIELDDISC | |||
YIELDMAT | |||
ZTEST |
@ -0,0 +1,187 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Cell_AdvancedValueBinder | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder | |||
{ | |||
/** | |||
* Bind value to a cell | |||
* | |||
* @param PHPExcel_Cell $cell Cell to bind value to | |||
* @param mixed $value Value to bind in cell | |||
* @return boolean | |||
*/ | |||
public function bindValue(PHPExcel_Cell $cell, $value = null) | |||
{ | |||
// sanitize UTF-8 strings | |||
if (is_string($value)) { | |||
$value = PHPExcel_Shared_String::SanitizeUTF8($value); | |||
} | |||
// Find out data type | |||
$dataType = parent::dataTypeForValue($value); | |||
// Style logic - strings | |||
if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) { | |||
// Test for booleans using locale-setting | |||
if ($value == PHPExcel_Calculation::getTRUE()) { | |||
$cell->setValueExplicit(true, PHPExcel_Cell_DataType::TYPE_BOOL); | |||
return true; | |||
} elseif ($value == PHPExcel_Calculation::getFALSE()) { | |||
$cell->setValueExplicit(false, PHPExcel_Cell_DataType::TYPE_BOOL); | |||
return true; | |||
} | |||
// Check for number in scientific format | |||
if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER.'$/', $value)) { | |||
$cell->setValueExplicit((float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
return true; | |||
} | |||
// Check for fraction | |||
if (preg_match('/^([+-]?)\s*([0-9]+)\s?\/\s*([0-9]+)$/', $value, $matches)) { | |||
// Convert value to number | |||
$value = $matches[2] / $matches[3]; | |||
if ($matches[1] == '-') { | |||
$value = 0 - $value; | |||
} | |||
$cell->setValueExplicit((float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode('??/??'); | |||
return true; | |||
} elseif (preg_match('/^([+-]?)([0-9]*) +([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { | |||
// Convert value to number | |||
$value = $matches[2] + ($matches[3] / $matches[4]); | |||
if ($matches[1] == '-') { | |||
$value = 0 - $value; | |||
} | |||
$cell->setValueExplicit((float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode('# ??/??'); | |||
return true; | |||
} | |||
// Check for percentage | |||
if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { | |||
// Convert value to number | |||
$value = (float) str_replace('%', '', $value) / 100; | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00); | |||
return true; | |||
} | |||
// Check for currency | |||
$currencyCode = PHPExcel_Shared_String::getCurrencyCode(); | |||
$decimalSeparator = PHPExcel_Shared_String::getDecimalSeparator(); | |||
$thousandsSeparator = PHPExcel_Shared_String::getThousandsSeparator(); | |||
if (preg_match('/^'.preg_quote($currencyCode).' *(\d{1,3}('.preg_quote($thousandsSeparator).'\d{3})*|(\d+))('.preg_quote($decimalSeparator).'\d{2})?$/', $value)) { | |||
// Convert value to number | |||
$value = (float) trim(str_replace(array($currencyCode, $thousandsSeparator, $decimalSeparator), array('', '', '.'), $value)); | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode( | |||
str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE) | |||
); | |||
return true; | |||
} elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { | |||
// Convert value to number | |||
$value = (float) trim(str_replace(array('$',','), '', $value)); | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE); | |||
return true; | |||
} | |||
// Check for time without seconds e.g. '9:45', '09:45' | |||
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { | |||
// Convert value to number | |||
list($h, $m) = explode(':', $value); | |||
$days = $h / 24 + $m / 1440; | |||
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3); | |||
return true; | |||
} | |||
// Check for time with seconds '9:45:59', '09:45:59' | |||
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { | |||
// Convert value to number | |||
list($h, $m, $s) = explode(':', $value); | |||
$days = $h / 24 + $m / 1440 + $s / 86400; | |||
// Convert value to number | |||
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4); | |||
return true; | |||
} | |||
// Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' | |||
if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { | |||
// Convert value to number | |||
$cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Determine style. Either there is a time part or not. Look for ':' | |||
if (strpos($value, ':') !== false) { | |||
$formatCode = 'yyyy-mm-dd h:mm'; | |||
} else { | |||
$formatCode = 'yyyy-mm-dd'; | |||
} | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode($formatCode); | |||
return true; | |||
} | |||
// Check for newline character "\n" | |||
if (strpos($value, "\n") !== false) { | |||
$value = PHPExcel_Shared_String::SanitizeUTF8($value); | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getAlignment()->setWrapText(true); | |||
return true; | |||
} | |||
} | |||
// Not bound yet? Use parent... | |||
return parent::bindValue($cell, $value); | |||
} | |||
} |
@ -0,0 +1,187 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Cell_AdvancedValueBinder | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder | |||
{ | |||
/** | |||
* Bind value to a cell | |||
* | |||
* @param PHPExcel_Cell $cell Cell to bind value to | |||
* @param mixed $value Value to bind in cell | |||
* @return boolean | |||
*/ | |||
public function bindValue(PHPExcel_Cell $cell, $value = null) | |||
{ | |||
// sanitize UTF-8 strings | |||
if (is_string($value)) { | |||
$value = PHPExcel_Shared_String::SanitizeUTF8($value); | |||
} | |||
// Find out data type | |||
$dataType = parent::dataTypeForValue($value); | |||
// Style logic - strings | |||
if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) { | |||
// Test for booleans using locale-setting | |||
if ($value == PHPExcel_Calculation::getTRUE()) { | |||
$cell->setValueExplicit(true, PHPExcel_Cell_DataType::TYPE_BOOL); | |||
return true; | |||
} elseif ($value == PHPExcel_Calculation::getFALSE()) { | |||
$cell->setValueExplicit(false, PHPExcel_Cell_DataType::TYPE_BOOL); | |||
return true; | |||
} | |||
// Check for number in scientific format | |||
if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER.'$/', $value)) { | |||
$cell->setValueExplicit((float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
return true; | |||
} | |||
// Check for fraction | |||
if (preg_match('/^([+-]?)\s*([0-9]+)\s?\/\s*([0-9]+)$/', $value, $matches)) { | |||
// Convert value to number | |||
$value = $matches[2] / $matches[3]; | |||
if ($matches[1] == '-') { | |||
$value = 0 - $value; | |||
} | |||
$cell->setValueExplicit((float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode('??/??'); | |||
return true; | |||
} elseif (preg_match('/^([+-]?)([0-9]*) +([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { | |||
// Convert value to number | |||
$value = $matches[2] + ($matches[3] / $matches[4]); | |||
if ($matches[1] == '-') { | |||
$value = 0 - $value; | |||
} | |||
$cell->setValueExplicit((float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode('# ??/??'); | |||
return true; | |||
} | |||
// Check for percentage | |||
if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { | |||
// Convert value to number | |||
$value = (float) str_replace('%', '', $value) / 100; | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00); | |||
return true; | |||
} | |||
// Check for currency | |||
$currencyCode = PHPExcel_Shared_String::getCurrencyCode(); | |||
$decimalSeparator = PHPExcel_Shared_String::getDecimalSeparator(); | |||
$thousandsSeparator = PHPExcel_Shared_String::getThousandsSeparator(); | |||
if (preg_match('/^'.preg_quote($currencyCode).' *(\d{1,3}('.preg_quote($thousandsSeparator).'\d{3})*|(\d+))('.preg_quote($decimalSeparator).'\d{2})?$/', $value)) { | |||
// Convert value to number | |||
$value = (float) trim(str_replace(array($currencyCode, $thousandsSeparator, $decimalSeparator), array('', '', '.'), $value)); | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode( | |||
str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE) | |||
); | |||
return true; | |||
} elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { | |||
// Convert value to number | |||
$value = (float) trim(str_replace(array('$',','), '', $value)); | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE); | |||
return true; | |||
} | |||
// Check for time without seconds e.g. '9:45', '09:45' | |||
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { | |||
// Convert value to number | |||
list($h, $m) = explode(':', $value); | |||
$days = $h / 24 + $m / 1440; | |||
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3); | |||
return true; | |||
} | |||
// Check for time with seconds '9:45:59', '09:45:59' | |||
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { | |||
// Convert value to number | |||
list($h, $m, $s) = explode(':', $value); | |||
$days = $h / 24 + $m / 1440 + $s / 86400; | |||
// Convert value to number | |||
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4); | |||
return true; | |||
} | |||
// Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' | |||
if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { | |||
// Convert value to number | |||
$cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC); | |||
// Determine style. Either there is a time part or not. Look for ':' | |||
if (strpos($value, ':') !== false) { | |||
$formatCode = 'yyyy-mm-dd h:mm'; | |||
} else { | |||
$formatCode = 'yyyy-mm-dd'; | |||
} | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getNumberFormat()->setFormatCode($formatCode); | |||
return true; | |||
} | |||
// Check for newline character "\n" | |||
if (strpos($value, "\n") !== false) { | |||
$value = PHPExcel_Shared_String::SanitizeUTF8($value); | |||
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); | |||
// Set style | |||
$cell->getWorksheet()->getStyle($cell->getCoordinate()) | |||
->getAlignment()->setWrapText(true); | |||
return true; | |||
} | |||
} | |||
// Not bound yet? Use parent... | |||
return parent::bindValue($cell, $value); | |||
} | |||
} |
@ -0,0 +1,115 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Cell_DataType | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_DataType | |||
{ | |||
/* Data types */ | |||
const TYPE_STRING2 = 'str'; | |||
const TYPE_STRING = 's'; | |||
const TYPE_FORMULA = 'f'; | |||
const TYPE_NUMERIC = 'n'; | |||
const TYPE_BOOL = 'b'; | |||
const TYPE_NULL = 'null'; | |||
const TYPE_INLINE = 'inlineStr'; | |||
const TYPE_ERROR = 'e'; | |||
/** | |||
* List of error codes | |||
* | |||
* @var array | |||
*/ | |||
private static $errorCodes = array( | |||
'#NULL!' => 0, | |||
'#DIV/0!' => 1, | |||
'#VALUE!' => 2, | |||
'#REF!' => 3, | |||
'#NAME?' => 4, | |||
'#NUM!' => 5, | |||
'#N/A' => 6 | |||
); | |||
/** | |||
* Get list of error codes | |||
* | |||
* @return array | |||
*/ | |||
public static function getErrorCodes() | |||
{ | |||
return self::$errorCodes; | |||
} | |||
/** | |||
* DataType for value | |||
* | |||
* @deprecated Replaced by PHPExcel_Cell_IValueBinder infrastructure, will be removed in version 1.8.0 | |||
* @param mixed $pValue | |||
* @return string | |||
*/ | |||
public static function dataTypeForValue($pValue = null) | |||
{ | |||
return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue); | |||
} | |||
/** | |||
* Check a string that it satisfies Excel requirements | |||
* | |||
* @param mixed Value to sanitize to an Excel string | |||
* @return mixed Sanitized value | |||
*/ | |||
public static function checkString($pValue = null) | |||
{ | |||
if ($pValue instanceof PHPExcel_RichText) { | |||
// TODO: Sanitize Rich-Text string (max. character count is 32,767) | |||
return $pValue; | |||
} | |||
// string must never be longer than 32,767 characters, truncate if necessary | |||
$pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); | |||
// we require that newline is represented as "\n" in core, not as "\r\n" or "\r" | |||
$pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); | |||
return $pValue; | |||
} | |||
/** | |||
* Check a value that it is a valid error code | |||
* | |||
* @param mixed Value to sanitize to an Excel error code | |||
* @return string Sanitized value | |||
*/ | |||
public static function checkErrorCode($pValue = null) | |||
{ | |||
$pValue = (string) $pValue; | |||
if (!array_key_exists($pValue, self::$errorCodes)) { | |||
$pValue = '#NULL!'; | |||
} | |||
return $pValue; | |||
} | |||
} |
@ -0,0 +1,492 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Cell_DataValidation | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_DataValidation | |||
{ | |||
/* Data validation types */ | |||
const TYPE_NONE = 'none'; | |||
const TYPE_CUSTOM = 'custom'; | |||
const TYPE_DATE = 'date'; | |||
const TYPE_DECIMAL = 'decimal'; | |||
const TYPE_LIST = 'list'; | |||
const TYPE_TEXTLENGTH = 'textLength'; | |||
const TYPE_TIME = 'time'; | |||
const TYPE_WHOLE = 'whole'; | |||
/* Data validation error styles */ | |||
const STYLE_STOP = 'stop'; | |||
const STYLE_WARNING = 'warning'; | |||
const STYLE_INFORMATION = 'information'; | |||
/* Data validation operators */ | |||
const OPERATOR_BETWEEN = 'between'; | |||
const OPERATOR_EQUAL = 'equal'; | |||
const OPERATOR_GREATERTHAN = 'greaterThan'; | |||
const OPERATOR_GREATERTHANOREQUAL = 'greaterThanOrEqual'; | |||
const OPERATOR_LESSTHAN = 'lessThan'; | |||
const OPERATOR_LESSTHANOREQUAL = 'lessThanOrEqual'; | |||
const OPERATOR_NOTBETWEEN = 'notBetween'; | |||
const OPERATOR_NOTEQUAL = 'notEqual'; | |||
/** | |||
* Formula 1 | |||
* | |||
* @var string | |||
*/ | |||
private $formula1; | |||
/** | |||
* Formula 2 | |||
* | |||
* @var string | |||
*/ | |||
private $formula2; | |||
/** | |||
* Type | |||
* | |||
* @var string | |||
*/ | |||
private $type = PHPExcel_Cell_DataValidation::TYPE_NONE; | |||
/** | |||
* Error style | |||
* | |||
* @var string | |||
*/ | |||
private $errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; | |||
/** | |||
* Operator | |||
* | |||
* @var string | |||
*/ | |||
private $operator; | |||
/** | |||
* Allow Blank | |||
* | |||
* @var boolean | |||
*/ | |||
private $allowBlank; | |||
/** | |||
* Show DropDown | |||
* | |||
* @var boolean | |||
*/ | |||
private $showDropDown; | |||
/** | |||
* Show InputMessage | |||
* | |||
* @var boolean | |||
*/ | |||
private $showInputMessage; | |||
/** | |||
* Show ErrorMessage | |||
* | |||
* @var boolean | |||
*/ | |||
private $showErrorMessage; | |||
/** | |||
* Error title | |||
* | |||
* @var string | |||
*/ | |||
private $errorTitle; | |||
/** | |||
* Error | |||
* | |||
* @var string | |||
*/ | |||
private $error; | |||
/** | |||
* Prompt title | |||
* | |||
* @var string | |||
*/ | |||
private $promptTitle; | |||
/** | |||
* Prompt | |||
* | |||
* @var string | |||
*/ | |||
private $prompt; | |||
/** | |||
* Create a new PHPExcel_Cell_DataValidation | |||
*/ | |||
public function __construct() | |||
{ | |||
// Initialise member variables | |||
$this->formula1 = ''; | |||
$this->formula2 = ''; | |||
$this->type = PHPExcel_Cell_DataValidation::TYPE_NONE; | |||
$this->errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; | |||
$this->operator = ''; | |||
$this->allowBlank = false; | |||
$this->showDropDown = false; | |||
$this->showInputMessage = false; | |||
$this->showErrorMessage = false; | |||
$this->errorTitle = ''; | |||
$this->error = ''; | |||
$this->promptTitle = ''; | |||
$this->prompt = ''; | |||
} | |||
/** | |||
* Get Formula 1 | |||
* | |||
* @return string | |||
*/ | |||
public function getFormula1() | |||
{ | |||
return $this->formula1; | |||
} | |||
/** | |||
* Set Formula 1 | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setFormula1($value = '') | |||
{ | |||
$this->formula1 = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Formula 2 | |||
* | |||
* @return string | |||
*/ | |||
public function getFormula2() | |||
{ | |||
return $this->formula2; | |||
} | |||
/** | |||
* Set Formula 2 | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setFormula2($value = '') | |||
{ | |||
$this->formula2 = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Type | |||
* | |||
* @return string | |||
*/ | |||
public function getType() | |||
{ | |||
return $this->type; | |||
} | |||
/** | |||
* Set Type | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setType($value = PHPExcel_Cell_DataValidation::TYPE_NONE) | |||
{ | |||
$this->type = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Error style | |||
* | |||
* @return string | |||
*/ | |||
public function getErrorStyle() | |||
{ | |||
return $this->errorStyle; | |||
} | |||
/** | |||
* Set Error style | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setErrorStyle($value = PHPExcel_Cell_DataValidation::STYLE_STOP) | |||
{ | |||
$this->errorStyle = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Operator | |||
* | |||
* @return string | |||
*/ | |||
public function getOperator() | |||
{ | |||
return $this->operator; | |||
} | |||
/** | |||
* Set Operator | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setOperator($value = '') | |||
{ | |||
$this->operator = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Allow Blank | |||
* | |||
* @return boolean | |||
*/ | |||
public function getAllowBlank() | |||
{ | |||
return $this->allowBlank; | |||
} | |||
/** | |||
* Set Allow Blank | |||
* | |||
* @param boolean $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setAllowBlank($value = false) | |||
{ | |||
$this->allowBlank = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Show DropDown | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowDropDown() | |||
{ | |||
return $this->showDropDown; | |||
} | |||
/** | |||
* Set Show DropDown | |||
* | |||
* @param boolean $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setShowDropDown($value = false) | |||
{ | |||
$this->showDropDown = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Show InputMessage | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowInputMessage() | |||
{ | |||
return $this->showInputMessage; | |||
} | |||
/** | |||
* Set Show InputMessage | |||
* | |||
* @param boolean $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setShowInputMessage($value = false) | |||
{ | |||
$this->showInputMessage = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Show ErrorMessage | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowErrorMessage() | |||
{ | |||
return $this->showErrorMessage; | |||
} | |||
/** | |||
* Set Show ErrorMessage | |||
* | |||
* @param boolean $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setShowErrorMessage($value = false) | |||
{ | |||
$this->showErrorMessage = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Error title | |||
* | |||
* @return string | |||
*/ | |||
public function getErrorTitle() | |||
{ | |||
return $this->errorTitle; | |||
} | |||
/** | |||
* Set Error title | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setErrorTitle($value = '') | |||
{ | |||
$this->errorTitle = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Error | |||
* | |||
* @return string | |||
*/ | |||
public function getError() | |||
{ | |||
return $this->error; | |||
} | |||
/** | |||
* Set Error | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setError($value = '') | |||
{ | |||
$this->error = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Prompt title | |||
* | |||
* @return string | |||
*/ | |||
public function getPromptTitle() | |||
{ | |||
return $this->promptTitle; | |||
} | |||
/** | |||
* Set Prompt title | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setPromptTitle($value = '') | |||
{ | |||
$this->promptTitle = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Prompt | |||
* | |||
* @return string | |||
*/ | |||
public function getPrompt() | |||
{ | |||
return $this->prompt; | |||
} | |||
/** | |||
* Set Prompt | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_DataValidation | |||
*/ | |||
public function setPrompt($value = '') | |||
{ | |||
$this->prompt = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get hash code | |||
* | |||
* @return string Hash code | |||
*/ | |||
public function getHashCode() | |||
{ | |||
return md5( | |||
$this->formula1 . | |||
$this->formula2 . | |||
$this->type = PHPExcel_Cell_DataValidation::TYPE_NONE . | |||
$this->errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP . | |||
$this->operator . | |||
($this->allowBlank ? 't' : 'f') . | |||
($this->showDropDown ? 't' : 'f') . | |||
($this->showInputMessage ? 't' : 'f') . | |||
($this->showErrorMessage ? 't' : 'f') . | |||
$this->errorTitle . | |||
$this->error . | |||
$this->promptTitle . | |||
$this->prompt . | |||
__CLASS__ | |||
); | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if (is_object($value)) { | |||
$this->$key = clone $value; | |||
} else { | |||
$this->$key = $value; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,102 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Cell_DefaultValueBinder | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder | |||
{ | |||
/** | |||
* Bind value to a cell | |||
* | |||
* @param PHPExcel_Cell $cell Cell to bind value to | |||
* @param mixed $value Value to bind in cell | |||
* @return boolean | |||
*/ | |||
public function bindValue(PHPExcel_Cell $cell, $value = null) | |||
{ | |||
// sanitize UTF-8 strings | |||
if (is_string($value)) { | |||
$value = PHPExcel_Shared_String::SanitizeUTF8($value); | |||
} elseif (is_object($value)) { | |||
// Handle any objects that might be injected | |||
if ($value instanceof DateTime) { | |||
$value = $value->format('Y-m-d H:i:s'); | |||
} elseif (!($value instanceof PHPExcel_RichText)) { | |||
$value = (string) $value; | |||
} | |||
} | |||
// Set value explicit | |||
$cell->setValueExplicit($value, self::dataTypeForValue($value)); | |||
// Done! | |||
return true; | |||
} | |||
/** | |||
* DataType for value | |||
* | |||
* @param mixed $pValue | |||
* @return string | |||
*/ | |||
public static function dataTypeForValue($pValue = null) | |||
{ | |||
// Match the value against a few data types | |||
if ($pValue === null) { | |||
return PHPExcel_Cell_DataType::TYPE_NULL; | |||
} elseif ($pValue === '') { | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} elseif ($pValue instanceof PHPExcel_RichText) { | |||
return PHPExcel_Cell_DataType::TYPE_INLINE; | |||
} elseif ($pValue[0] === '=' && strlen($pValue) > 1) { | |||
return PHPExcel_Cell_DataType::TYPE_FORMULA; | |||
} elseif (is_bool($pValue)) { | |||
return PHPExcel_Cell_DataType::TYPE_BOOL; | |||
} elseif (is_float($pValue) || is_int($pValue)) { | |||
return PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
} elseif (preg_match('/^[\+\-]?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)([Ee][\-\+]?[0-2]?\d{1,3})?$/', $pValue)) { | |||
$tValue = ltrim($pValue, '+-'); | |||
if (is_string($pValue) && $tValue[0] === '0' && strlen($tValue) > 1 && $tValue[1] !== '.') { | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} elseif ((strpos($pValue, '.') === false) && ($pValue > PHP_INT_MAX)) { | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} | |||
return PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
} elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { | |||
return PHPExcel_Cell_DataType::TYPE_ERROR; | |||
} | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} | |||
} |
@ -0,0 +1,102 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Cell_DefaultValueBinder | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder | |||
{ | |||
/** | |||
* Bind value to a cell | |||
* | |||
* @param PHPExcel_Cell $cell Cell to bind value to | |||
* @param mixed $value Value to bind in cell | |||
* @return boolean | |||
*/ | |||
public function bindValue(PHPExcel_Cell $cell, $value = null) | |||
{ | |||
// sanitize UTF-8 strings | |||
if (is_string($value)) { | |||
$value = PHPExcel_Shared_String::SanitizeUTF8($value); | |||
} elseif (is_object($value)) { | |||
// Handle any objects that might be injected | |||
if ($value instanceof DateTime) { | |||
$value = $value->format('Y-m-d H:i:s'); | |||
} elseif (!($value instanceof PHPExcel_RichText)) { | |||
$value = (string) $value; | |||
} | |||
} | |||
// Set value explicit | |||
$cell->setValueExplicit($value, self::dataTypeForValue($value)); | |||
// Done! | |||
return true; | |||
} | |||
/** | |||
* DataType for value | |||
* | |||
* @param mixed $pValue | |||
* @return string | |||
*/ | |||
public static function dataTypeForValue($pValue = null) | |||
{ | |||
// Match the value against a few data types | |||
if ($pValue === null) { | |||
return PHPExcel_Cell_DataType::TYPE_NULL; | |||
} elseif ($pValue === '') { | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} elseif ($pValue instanceof PHPExcel_RichText) { | |||
return PHPExcel_Cell_DataType::TYPE_INLINE; | |||
} elseif ($pValue{0} === '=' && strlen($pValue) > 1) { | |||
return PHPExcel_Cell_DataType::TYPE_FORMULA; | |||
} elseif (is_bool($pValue)) { | |||
return PHPExcel_Cell_DataType::TYPE_BOOL; | |||
} elseif (is_float($pValue) || is_int($pValue)) { | |||
return PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
} elseif (preg_match('/^[\+\-]?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)([Ee][\-\+]?[0-2]?\d{1,3})?$/', $pValue)) { | |||
$tValue = ltrim($pValue, '+-'); | |||
if (is_string($pValue) && $tValue{0} === '0' && strlen($tValue) > 1 && $tValue{1} !== '.') { | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} elseif ((strpos($pValue, '.') === false) && ($pValue > PHP_INT_MAX)) { | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} | |||
return PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
} elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { | |||
return PHPExcel_Cell_DataType::TYPE_ERROR; | |||
} | |||
return PHPExcel_Cell_DataType::TYPE_STRING; | |||
} | |||
} |
@ -0,0 +1,124 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Cell_Hyperlink | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Cell_Hyperlink | |||
{ | |||
/** | |||
* URL to link the cell to | |||
* | |||
* @var string | |||
*/ | |||
private $url; | |||
/** | |||
* Tooltip to display on the hyperlink | |||
* | |||
* @var string | |||
*/ | |||
private $tooltip; | |||
/** | |||
* Create a new PHPExcel_Cell_Hyperlink | |||
* | |||
* @param string $pUrl Url to link the cell to | |||
* @param string $pTooltip Tooltip to display on the hyperlink | |||
*/ | |||
public function __construct($pUrl = '', $pTooltip = '') | |||
{ | |||
// Initialise member variables | |||
$this->url = $pUrl; | |||
$this->tooltip = $pTooltip; | |||
} | |||
/** | |||
* Get URL | |||
* | |||
* @return string | |||
*/ | |||
public function getUrl() | |||
{ | |||
return $this->url; | |||
} | |||
/** | |||
* Set URL | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_Hyperlink | |||
*/ | |||
public function setUrl($value = '') | |||
{ | |||
$this->url = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get tooltip | |||
* | |||
* @return string | |||
*/ | |||
public function getTooltip() | |||
{ | |||
return $this->tooltip; | |||
} | |||
/** | |||
* Set tooltip | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Cell_Hyperlink | |||
*/ | |||
public function setTooltip($value = '') | |||
{ | |||
$this->tooltip = $value; | |||
return $this; | |||
} | |||
/** | |||
* Is this hyperlink internal? (to another worksheet) | |||
* | |||
* @return boolean | |||
*/ | |||
public function isInternal() | |||
{ | |||
return strpos($this->url, 'sheet://') !== false; | |||
} | |||
/** | |||
* Get hash code | |||
* | |||
* @return string Hash code | |||
*/ | |||
public function getHashCode() | |||
{ | |||
return md5( | |||
$this->url . | |||
$this->tooltip . | |||
__CLASS__ | |||
); | |||
} | |||
} |
@ -0,0 +1,47 @@ | |||
<?php | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
/** | |||
* PHPExcel_Cell_IValueBinder | |||
* | |||
* @category PHPExcel | |||
* @package PHPExcel_Cell | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
*/ | |||
interface PHPExcel_Cell_IValueBinder | |||
{ | |||
/** | |||
* Bind value to a cell | |||
* | |||
* @param PHPExcel_Cell $cell Cell to bind value to | |||
* @param mixed $value Value to bind in cell | |||
* @return boolean | |||
*/ | |||
public function bindValue(PHPExcel_Cell $cell, $value = null); | |||
} |
@ -0,0 +1,680 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Chart | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart | |||
{ | |||
/** | |||
* Chart Name | |||
* | |||
* @var string | |||
*/ | |||
private $name = ''; | |||
/** | |||
* Worksheet | |||
* | |||
* @var PHPExcel_Worksheet | |||
*/ | |||
private $worksheet; | |||
/** | |||
* Chart Title | |||
* | |||
* @var PHPExcel_Chart_Title | |||
*/ | |||
private $title; | |||
/** | |||
* Chart Legend | |||
* | |||
* @var PHPExcel_Chart_Legend | |||
*/ | |||
private $legend; | |||
/** | |||
* X-Axis Label | |||
* | |||
* @var PHPExcel_Chart_Title | |||
*/ | |||
private $xAxisLabel; | |||
/** | |||
* Y-Axis Label | |||
* | |||
* @var PHPExcel_Chart_Title | |||
*/ | |||
private $yAxisLabel; | |||
/** | |||
* Chart Plot Area | |||
* | |||
* @var PHPExcel_Chart_PlotArea | |||
*/ | |||
private $plotArea; | |||
/** | |||
* Plot Visible Only | |||
* | |||
* @var boolean | |||
*/ | |||
private $plotVisibleOnly = true; | |||
/** | |||
* Display Blanks as | |||
* | |||
* @var string | |||
*/ | |||
private $displayBlanksAs = '0'; | |||
/** | |||
* Chart Asix Y as | |||
* | |||
* @var PHPExcel_Chart_Axis | |||
*/ | |||
private $yAxis; | |||
/** | |||
* Chart Asix X as | |||
* | |||
* @var PHPExcel_Chart_Axis | |||
*/ | |||
private $xAxis; | |||
/** | |||
* Chart Major Gridlines as | |||
* | |||
* @var PHPExcel_Chart_GridLines | |||
*/ | |||
private $majorGridlines; | |||
/** | |||
* Chart Minor Gridlines as | |||
* | |||
* @var PHPExcel_Chart_GridLines | |||
*/ | |||
private $minorGridlines; | |||
/** | |||
* Top-Left Cell Position | |||
* | |||
* @var string | |||
*/ | |||
private $topLeftCellRef = 'A1'; | |||
/** | |||
* Top-Left X-Offset | |||
* | |||
* @var integer | |||
*/ | |||
private $topLeftXOffset = 0; | |||
/** | |||
* Top-Left Y-Offset | |||
* | |||
* @var integer | |||
*/ | |||
private $topLeftYOffset = 0; | |||
/** | |||
* Bottom-Right Cell Position | |||
* | |||
* @var string | |||
*/ | |||
private $bottomRightCellRef = 'A1'; | |||
/** | |||
* Bottom-Right X-Offset | |||
* | |||
* @var integer | |||
*/ | |||
private $bottomRightXOffset = 10; | |||
/** | |||
* Bottom-Right Y-Offset | |||
* | |||
* @var integer | |||
*/ | |||
private $bottomRightYOffset = 10; | |||
/** | |||
* Create a new PHPExcel_Chart | |||
*/ | |||
public function __construct($name, PHPExcel_Chart_Title $title = null, PHPExcel_Chart_Legend $legend = null, PHPExcel_Chart_PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = '0', PHPExcel_Chart_Title $xAxisLabel = null, PHPExcel_Chart_Title $yAxisLabel = null, PHPExcel_Chart_Axis $xAxis = null, PHPExcel_Chart_Axis $yAxis = null, PHPExcel_Chart_GridLines $majorGridlines = null, PHPExcel_Chart_GridLines $minorGridlines = null) | |||
{ | |||
$this->name = $name; | |||
$this->title = $title; | |||
$this->legend = $legend; | |||
$this->xAxisLabel = $xAxisLabel; | |||
$this->yAxisLabel = $yAxisLabel; | |||
$this->plotArea = $plotArea; | |||
$this->plotVisibleOnly = $plotVisibleOnly; | |||
$this->displayBlanksAs = $displayBlanksAs; | |||
$this->xAxis = $xAxis; | |||
$this->yAxis = $yAxis; | |||
$this->majorGridlines = $majorGridlines; | |||
$this->minorGridlines = $minorGridlines; | |||
} | |||
/** | |||
* Get Name | |||
* | |||
* @return string | |||
*/ | |||
public function getName() | |||
{ | |||
return $this->name; | |||
} | |||
/** | |||
* Get Worksheet | |||
* | |||
* @return PHPExcel_Worksheet | |||
*/ | |||
public function getWorksheet() | |||
{ | |||
return $this->worksheet; | |||
} | |||
/** | |||
* Set Worksheet | |||
* | |||
* @param PHPExcel_Worksheet $pValue | |||
* @throws PHPExcel_Chart_Exception | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setWorksheet(PHPExcel_Worksheet $pValue = null) | |||
{ | |||
$this->worksheet = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Title | |||
* | |||
* @return PHPExcel_Chart_Title | |||
*/ | |||
public function getTitle() | |||
{ | |||
return $this->title; | |||
} | |||
/** | |||
* Set Title | |||
* | |||
* @param PHPExcel_Chart_Title $title | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setTitle(PHPExcel_Chart_Title $title) | |||
{ | |||
$this->title = $title; | |||
return $this; | |||
} | |||
/** | |||
* Get Legend | |||
* | |||
* @return PHPExcel_Chart_Legend | |||
*/ | |||
public function getLegend() | |||
{ | |||
return $this->legend; | |||
} | |||
/** | |||
* Set Legend | |||
* | |||
* @param PHPExcel_Chart_Legend $legend | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setLegend(PHPExcel_Chart_Legend $legend) | |||
{ | |||
$this->legend = $legend; | |||
return $this; | |||
} | |||
/** | |||
* Get X-Axis Label | |||
* | |||
* @return PHPExcel_Chart_Title | |||
*/ | |||
public function getXAxisLabel() | |||
{ | |||
return $this->xAxisLabel; | |||
} | |||
/** | |||
* Set X-Axis Label | |||
* | |||
* @param PHPExcel_Chart_Title $label | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setXAxisLabel(PHPExcel_Chart_Title $label) | |||
{ | |||
$this->xAxisLabel = $label; | |||
return $this; | |||
} | |||
/** | |||
* Get Y-Axis Label | |||
* | |||
* @return PHPExcel_Chart_Title | |||
*/ | |||
public function getYAxisLabel() | |||
{ | |||
return $this->yAxisLabel; | |||
} | |||
/** | |||
* Set Y-Axis Label | |||
* | |||
* @param PHPExcel_Chart_Title $label | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setYAxisLabel(PHPExcel_Chart_Title $label) | |||
{ | |||
$this->yAxisLabel = $label; | |||
return $this; | |||
} | |||
/** | |||
* Get Plot Area | |||
* | |||
* @return PHPExcel_Chart_PlotArea | |||
*/ | |||
public function getPlotArea() | |||
{ | |||
return $this->plotArea; | |||
} | |||
/** | |||
* Get Plot Visible Only | |||
* | |||
* @return boolean | |||
*/ | |||
public function getPlotVisibleOnly() | |||
{ | |||
return $this->plotVisibleOnly; | |||
} | |||
/** | |||
* Set Plot Visible Only | |||
* | |||
* @param boolean $plotVisibleOnly | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setPlotVisibleOnly($plotVisibleOnly = true) | |||
{ | |||
$this->plotVisibleOnly = $plotVisibleOnly; | |||
return $this; | |||
} | |||
/** | |||
* Get Display Blanks as | |||
* | |||
* @return string | |||
*/ | |||
public function getDisplayBlanksAs() | |||
{ | |||
return $this->displayBlanksAs; | |||
} | |||
/** | |||
* Set Display Blanks as | |||
* | |||
* @param string $displayBlanksAs | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setDisplayBlanksAs($displayBlanksAs = '0') | |||
{ | |||
$this->displayBlanksAs = $displayBlanksAs; | |||
} | |||
/** | |||
* Get yAxis | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
public function getChartAxisY() | |||
{ | |||
if ($this->yAxis !== null) { | |||
return $this->yAxis; | |||
} | |||
return new PHPExcel_Chart_Axis(); | |||
} | |||
/** | |||
* Get xAxis | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
public function getChartAxisX() | |||
{ | |||
if ($this->xAxis !== null) { | |||
return $this->xAxis; | |||
} | |||
return new PHPExcel_Chart_Axis(); | |||
} | |||
/** | |||
* Get Major Gridlines | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
public function getMajorGridlines() | |||
{ | |||
if ($this->majorGridlines !== null) { | |||
return $this->majorGridlines; | |||
} | |||
return new PHPExcel_Chart_GridLines(); | |||
} | |||
/** | |||
* Get Minor Gridlines | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
public function getMinorGridlines() | |||
{ | |||
if ($this->minorGridlines !== null) { | |||
return $this->minorGridlines; | |||
} | |||
return new PHPExcel_Chart_GridLines(); | |||
} | |||
/** | |||
* Set the Top Left position for the chart | |||
* | |||
* @param string $cell | |||
* @param integer $xOffset | |||
* @param integer $yOffset | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setTopLeftPosition($cell, $xOffset = null, $yOffset = null) | |||
{ | |||
$this->topLeftCellRef = $cell; | |||
if (!is_null($xOffset)) { | |||
$this->setTopLeftXOffset($xOffset); | |||
} | |||
if (!is_null($yOffset)) { | |||
$this->setTopLeftYOffset($yOffset); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get the top left position of the chart | |||
* | |||
* @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell | |||
*/ | |||
public function getTopLeftPosition() | |||
{ | |||
return array( | |||
'cell' => $this->topLeftCellRef, | |||
'xOffset' => $this->topLeftXOffset, | |||
'yOffset' => $this->topLeftYOffset | |||
); | |||
} | |||
/** | |||
* Get the cell address where the top left of the chart is fixed | |||
* | |||
* @return string | |||
*/ | |||
public function getTopLeftCell() | |||
{ | |||
return $this->topLeftCellRef; | |||
} | |||
/** | |||
* Set the Top Left cell position for the chart | |||
* | |||
* @param string $cell | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setTopLeftCell($cell) | |||
{ | |||
$this->topLeftCellRef = $cell; | |||
return $this; | |||
} | |||
/** | |||
* Set the offset position within the Top Left cell for the chart | |||
* | |||
* @param integer $xOffset | |||
* @param integer $yOffset | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setTopLeftOffset($xOffset = null, $yOffset = null) | |||
{ | |||
if (!is_null($xOffset)) { | |||
$this->setTopLeftXOffset($xOffset); | |||
} | |||
if (!is_null($yOffset)) { | |||
$this->setTopLeftYOffset($yOffset); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get the offset position within the Top Left cell for the chart | |||
* | |||
* @return integer[] | |||
*/ | |||
public function getTopLeftOffset() | |||
{ | |||
return array( | |||
'X' => $this->topLeftXOffset, | |||
'Y' => $this->topLeftYOffset | |||
); | |||
} | |||
public function setTopLeftXOffset($xOffset) | |||
{ | |||
$this->topLeftXOffset = $xOffset; | |||
return $this; | |||
} | |||
public function getTopLeftXOffset() | |||
{ | |||
return $this->topLeftXOffset; | |||
} | |||
public function setTopLeftYOffset($yOffset) | |||
{ | |||
$this->topLeftYOffset = $yOffset; | |||
return $this; | |||
} | |||
public function getTopLeftYOffset() | |||
{ | |||
return $this->topLeftYOffset; | |||
} | |||
/** | |||
* Set the Bottom Right position of the chart | |||
* | |||
* @param string $cell | |||
* @param integer $xOffset | |||
* @param integer $yOffset | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setBottomRightPosition($cell, $xOffset = null, $yOffset = null) | |||
{ | |||
$this->bottomRightCellRef = $cell; | |||
if (!is_null($xOffset)) { | |||
$this->setBottomRightXOffset($xOffset); | |||
} | |||
if (!is_null($yOffset)) { | |||
$this->setBottomRightYOffset($yOffset); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get the bottom right position of the chart | |||
* | |||
* @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell | |||
*/ | |||
public function getBottomRightPosition() | |||
{ | |||
return array( | |||
'cell' => $this->bottomRightCellRef, | |||
'xOffset' => $this->bottomRightXOffset, | |||
'yOffset' => $this->bottomRightYOffset | |||
); | |||
} | |||
public function setBottomRightCell($cell) | |||
{ | |||
$this->bottomRightCellRef = $cell; | |||
return $this; | |||
} | |||
/** | |||
* Get the cell address where the bottom right of the chart is fixed | |||
* | |||
* @return string | |||
*/ | |||
public function getBottomRightCell() | |||
{ | |||
return $this->bottomRightCellRef; | |||
} | |||
/** | |||
* Set the offset position within the Bottom Right cell for the chart | |||
* | |||
* @param integer $xOffset | |||
* @param integer $yOffset | |||
* @return PHPExcel_Chart | |||
*/ | |||
public function setBottomRightOffset($xOffset = null, $yOffset = null) | |||
{ | |||
if (!is_null($xOffset)) { | |||
$this->setBottomRightXOffset($xOffset); | |||
} | |||
if (!is_null($yOffset)) { | |||
$this->setBottomRightYOffset($yOffset); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get the offset position within the Bottom Right cell for the chart | |||
* | |||
* @return integer[] | |||
*/ | |||
public function getBottomRightOffset() | |||
{ | |||
return array( | |||
'X' => $this->bottomRightXOffset, | |||
'Y' => $this->bottomRightYOffset | |||
); | |||
} | |||
public function setBottomRightXOffset($xOffset) | |||
{ | |||
$this->bottomRightXOffset = $xOffset; | |||
return $this; | |||
} | |||
public function getBottomRightXOffset() | |||
{ | |||
return $this->bottomRightXOffset; | |||
} | |||
public function setBottomRightYOffset($yOffset) | |||
{ | |||
$this->bottomRightYOffset = $yOffset; | |||
return $this; | |||
} | |||
public function getBottomRightYOffset() | |||
{ | |||
return $this->bottomRightYOffset; | |||
} | |||
public function refresh() | |||
{ | |||
if ($this->worksheet !== null) { | |||
$this->plotArea->refresh($this->worksheet); | |||
} | |||
} | |||
public function render($outputDestination = null) | |||
{ | |||
$libraryName = PHPExcel_Settings::getChartRendererName(); | |||
if (is_null($libraryName)) { | |||
return false; | |||
} | |||
// Ensure that data series values are up-to-date before we render | |||
$this->refresh(); | |||
$libraryPath = PHPExcel_Settings::getChartRendererPath(); | |||
$includePath = str_replace('\\', '/', get_include_path()); | |||
$rendererPath = str_replace('\\', '/', $libraryPath); | |||
if (strpos($rendererPath, $includePath) === false) { | |||
set_include_path(get_include_path() . PATH_SEPARATOR . $libraryPath); | |||
} | |||
$rendererName = 'PHPExcel_Chart_Renderer_'.$libraryName; | |||
$renderer = new $rendererName($this); | |||
if ($outputDestination == 'php://output') { | |||
$outputDestination = null; | |||
} | |||
return $renderer->render($outputDestination); | |||
} | |||
} |
@ -0,0 +1,561 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Wiktor Trzonkowski | |||
* Date: 6/17/14 | |||
* Time: 12:11 PM | |||
*/ | |||
class PHPExcel_Chart_Axis extends PHPExcel_Chart_Properties | |||
{ | |||
/** | |||
* Axis Number | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $axisNumber = array( | |||
'format' => self::FORMAT_CODE_GENERAL, | |||
'source_linked' => 1 | |||
); | |||
/** | |||
* Axis Options | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $axisOptions = array( | |||
'minimum' => null, | |||
'maximum' => null, | |||
'major_unit' => null, | |||
'minor_unit' => null, | |||
'orientation' => self::ORIENTATION_NORMAL, | |||
'minor_tick_mark' => self::TICK_MARK_NONE, | |||
'major_tick_mark' => self::TICK_MARK_NONE, | |||
'axis_labels' => self::AXIS_LABELS_NEXT_TO, | |||
'horizontal_crosses' => self::HORIZONTAL_CROSSES_AUTOZERO, | |||
'horizontal_crosses_value' => null | |||
); | |||
/** | |||
* Fill Properties | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $fillProperties = array( | |||
'type' => self::EXCEL_COLOR_TYPE_ARGB, | |||
'value' => null, | |||
'alpha' => 0 | |||
); | |||
/** | |||
* Line Properties | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $lineProperties = array( | |||
'type' => self::EXCEL_COLOR_TYPE_ARGB, | |||
'value' => null, | |||
'alpha' => 0 | |||
); | |||
/** | |||
* Line Style Properties | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $lineStyleProperties = array( | |||
'width' => '9525', | |||
'compound' => self::LINE_STYLE_COMPOUND_SIMPLE, | |||
'dash' => self::LINE_STYLE_DASH_SOLID, | |||
'cap' => self::LINE_STYLE_CAP_FLAT, | |||
'join' => self::LINE_STYLE_JOIN_BEVEL, | |||
'arrow' => array( | |||
'head' => array( | |||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, | |||
'size' => self::LINE_STYLE_ARROW_SIZE_5 | |||
), | |||
'end' => array( | |||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, | |||
'size' => self::LINE_STYLE_ARROW_SIZE_8 | |||
), | |||
) | |||
); | |||
/** | |||
* Shadow Properties | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $shadowProperties = array( | |||
'presets' => self::SHADOW_PRESETS_NOSHADOW, | |||
'effect' => null, | |||
'color' => array( | |||
'type' => self::EXCEL_COLOR_TYPE_STANDARD, | |||
'value' => 'black', | |||
'alpha' => 40, | |||
), | |||
'size' => array( | |||
'sx' => null, | |||
'sy' => null, | |||
'kx' => null | |||
), | |||
'blur' => null, | |||
'direction' => null, | |||
'distance' => null, | |||
'algn' => null, | |||
'rotWithShape' => null | |||
); | |||
/** | |||
* Glow Properties | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $glowProperties = array( | |||
'size' => null, | |||
'color' => array( | |||
'type' => self::EXCEL_COLOR_TYPE_STANDARD, | |||
'value' => 'black', | |||
'alpha' => 40 | |||
) | |||
); | |||
/** | |||
* Soft Edge Properties | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $softEdges = array( | |||
'size' => null | |||
); | |||
/** | |||
* Get Series Data Type | |||
* | |||
* @return string | |||
*/ | |||
public function setAxisNumberProperties($format_code) | |||
{ | |||
$this->axisNumber['format'] = (string) $format_code; | |||
$this->axisNumber['source_linked'] = 0; | |||
} | |||
/** | |||
* Get Axis Number Format Data Type | |||
* | |||
* @return string | |||
*/ | |||
public function getAxisNumberFormat() | |||
{ | |||
return $this->axisNumber['format']; | |||
} | |||
/** | |||
* Get Axis Number Source Linked | |||
* | |||
* @return string | |||
*/ | |||
public function getAxisNumberSourceLinked() | |||
{ | |||
return (string) $this->axisNumber['source_linked']; | |||
} | |||
/** | |||
* Set Axis Options Properties | |||
* | |||
* @param string $axis_labels | |||
* @param string $horizontal_crosses_value | |||
* @param string $horizontal_crosses | |||
* @param string $axis_orientation | |||
* @param string $major_tmt | |||
* @param string $minor_tmt | |||
* @param string $minimum | |||
* @param string $maximum | |||
* @param string $major_unit | |||
* @param string $minor_unit | |||
* | |||
*/ | |||
public function setAxisOptionsProperties($axis_labels, $horizontal_crosses_value = null, $horizontal_crosses = null, $axis_orientation = null, $major_tmt = null, $minor_tmt = null, $minimum = null, $maximum = null, $major_unit = null, $minor_unit = null) | |||
{ | |||
$this->axisOptions['axis_labels'] = (string) $axis_labels; | |||
($horizontal_crosses_value !== null) ? $this->axisOptions['horizontal_crosses_value'] = (string) $horizontal_crosses_value : null; | |||
($horizontal_crosses !== null) ? $this->axisOptions['horizontal_crosses'] = (string) $horizontal_crosses : null; | |||
($axis_orientation !== null) ? $this->axisOptions['orientation'] = (string) $axis_orientation : null; | |||
($major_tmt !== null) ? $this->axisOptions['major_tick_mark'] = (string) $major_tmt : null; | |||
($minor_tmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minor_tmt : null; | |||
($minor_tmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minor_tmt : null; | |||
($minimum !== null) ? $this->axisOptions['minimum'] = (string) $minimum : null; | |||
($maximum !== null) ? $this->axisOptions['maximum'] = (string) $maximum : null; | |||
($major_unit !== null) ? $this->axisOptions['major_unit'] = (string) $major_unit : null; | |||
($minor_unit !== null) ? $this->axisOptions['minor_unit'] = (string) $minor_unit : null; | |||
} | |||
/** | |||
* Get Axis Options Property | |||
* | |||
* @param string $property | |||
* | |||
* @return string | |||
*/ | |||
public function getAxisOptionsProperty($property) | |||
{ | |||
return $this->axisOptions[$property]; | |||
} | |||
/** | |||
* Set Axis Orientation Property | |||
* | |||
* @param string $orientation | |||
* | |||
*/ | |||
public function setAxisOrientation($orientation) | |||
{ | |||
$this->orientation = (string) $orientation; | |||
} | |||
/** | |||
* Set Fill Property | |||
* | |||
* @param string $color | |||
* @param int $alpha | |||
* @param string $type | |||
* | |||
*/ | |||
public function setFillParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB) | |||
{ | |||
$this->fillProperties = $this->setColorProperties($color, $alpha, $type); | |||
} | |||
/** | |||
* Set Line Property | |||
* | |||
* @param string $color | |||
* @param int $alpha | |||
* @param string $type | |||
* | |||
*/ | |||
public function setLineParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB) | |||
{ | |||
$this->lineProperties = $this->setColorProperties($color, $alpha, $type); | |||
} | |||
/** | |||
* Get Fill Property | |||
* | |||
* @param string $property | |||
* | |||
* @return string | |||
*/ | |||
public function getFillProperty($property) | |||
{ | |||
return $this->fillProperties[$property]; | |||
} | |||
/** | |||
* Get Line Property | |||
* | |||
* @param string $property | |||
* | |||
* @return string | |||
*/ | |||
public function getLineProperty($property) | |||
{ | |||
return $this->lineProperties[$property]; | |||
} | |||
/** | |||
* Set Line Style Properties | |||
* | |||
* @param float $line_width | |||
* @param string $compound_type | |||
* @param string $dash_type | |||
* @param string $cap_type | |||
* @param string $join_type | |||
* @param string $head_arrow_type | |||
* @param string $head_arrow_size | |||
* @param string $end_arrow_type | |||
* @param string $end_arrow_size | |||
* | |||
*/ | |||
public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null) | |||
{ | |||
(!is_null($line_width)) ? $this->lineStyleProperties['width'] = $this->getExcelPointsWidth((float) $line_width) : null; | |||
(!is_null($compound_type)) ? $this->lineStyleProperties['compound'] = (string) $compound_type : null; | |||
(!is_null($dash_type)) ? $this->lineStyleProperties['dash'] = (string) $dash_type : null; | |||
(!is_null($cap_type)) ? $this->lineStyleProperties['cap'] = (string) $cap_type : null; | |||
(!is_null($join_type)) ? $this->lineStyleProperties['join'] = (string) $join_type : null; | |||
(!is_null($head_arrow_type)) ? $this->lineStyleProperties['arrow']['head']['type'] = (string) $head_arrow_type : null; | |||
(!is_null($head_arrow_size)) ? $this->lineStyleProperties['arrow']['head']['size'] = (string) $head_arrow_size : null; | |||
(!is_null($end_arrow_type)) ? $this->lineStyleProperties['arrow']['end']['type'] = (string) $end_arrow_type : null; | |||
(!is_null($end_arrow_size)) ? $this->lineStyleProperties['arrow']['end']['size'] = (string) $end_arrow_size : null; | |||
} | |||
/** | |||
* Get Line Style Property | |||
* | |||
* @param array|string $elements | |||
* | |||
* @return string | |||
*/ | |||
public function getLineStyleProperty($elements) | |||
{ | |||
return $this->getArrayElementsValue($this->lineStyleProperties, $elements); | |||
} | |||
/** | |||
* Get Line Style Arrow Excel Width | |||
* | |||
* @param string $arrow | |||
* | |||
* @return string | |||
*/ | |||
public function getLineStyleArrowWidth($arrow) | |||
{ | |||
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'w'); | |||
} | |||
/** | |||
* Get Line Style Arrow Excel Length | |||
* | |||
* @param string $arrow | |||
* | |||
* @return string | |||
*/ | |||
public function getLineStyleArrowLength($arrow) | |||
{ | |||
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'len'); | |||
} | |||
/** | |||
* Set Shadow Properties | |||
* | |||
* @param int $shadow_presets | |||
* @param string $sh_color_value | |||
* @param string $sh_color_type | |||
* @param string $sh_color_alpha | |||
* @param float $sh_blur | |||
* @param int $sh_angle | |||
* @param float $sh_distance | |||
* | |||
*/ | |||
public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null) | |||
{ | |||
$this->setShadowPresetsProperties((int) $sh_presets) | |||
->setShadowColor( | |||
is_null($sh_color_value) ? $this->shadowProperties['color']['value'] : $sh_color_value, | |||
is_null($sh_color_alpha) ? (int) $this->shadowProperties['color']['alpha'] : $sh_color_alpha, | |||
is_null($sh_color_type) ? $this->shadowProperties['color']['type'] : $sh_color_type | |||
) | |||
->setShadowBlur($sh_blur) | |||
->setShadowAngle($sh_angle) | |||
->setShadowDistance($sh_distance); | |||
} | |||
/** | |||
* Set Shadow Color | |||
* | |||
* @param int $shadow_presets | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setShadowPresetsProperties($shadow_presets) | |||
{ | |||
$this->shadowProperties['presets'] = $shadow_presets; | |||
$this->setShadowProperiesMapValues($this->getShadowPresetsMap($shadow_presets)); | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Properties from Maped Values | |||
* | |||
* @param array $properties_map | |||
* @param * $reference | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setShadowProperiesMapValues(array $properties_map, &$reference = null) | |||
{ | |||
$base_reference = $reference; | |||
foreach ($properties_map as $property_key => $property_val) { | |||
if (is_array($property_val)) { | |||
if ($reference === null) { | |||
$reference = & $this->shadowProperties[$property_key]; | |||
} else { | |||
$reference = & $reference[$property_key]; | |||
} | |||
$this->setShadowProperiesMapValues($property_val, $reference); | |||
} else { | |||
if ($base_reference === null) { | |||
$this->shadowProperties[$property_key] = $property_val; | |||
} else { | |||
$reference[$property_key] = $property_val; | |||
} | |||
} | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Color | |||
* | |||
* @param string $color | |||
* @param int $alpha | |||
* @param string $type | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setShadowColor($color, $alpha, $type) | |||
{ | |||
$this->shadowProperties['color'] = $this->setColorProperties($color, $alpha, $type); | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Blur | |||
* | |||
* @param float $blur | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setShadowBlur($blur) | |||
{ | |||
if ($blur !== null) { | |||
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Angle | |||
* | |||
* @param int $angle | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setShadowAngle($angle) | |||
{ | |||
if ($angle !== null) { | |||
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Distance | |||
* | |||
* @param float $distance | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setShadowDistance($distance) | |||
{ | |||
if ($distance !== null) { | |||
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get Glow Property | |||
* | |||
* @param float $size | |||
* @param string $color_value | |||
* @param int $color_alpha | |||
* @param string $color_type | |||
*/ | |||
public function getShadowProperty($elements) | |||
{ | |||
return $this->getArrayElementsValue($this->shadowProperties, $elements); | |||
} | |||
/** | |||
* Set Glow Properties | |||
* | |||
* @param float $size | |||
* @param string $color_value | |||
* @param int $color_alpha | |||
* @param string $color_type | |||
*/ | |||
public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null) | |||
{ | |||
$this->setGlowSize($size) | |||
->setGlowColor( | |||
is_null($color_value) ? $this->glowProperties['color']['value'] : $color_value, | |||
is_null($color_alpha) ? (int) $this->glowProperties['color']['alpha'] : $color_alpha, | |||
is_null($color_type) ? $this->glowProperties['color']['type'] : $color_type | |||
); | |||
} | |||
/** | |||
* Get Glow Property | |||
* | |||
* @param array|string $property | |||
* | |||
* @return string | |||
*/ | |||
public function getGlowProperty($property) | |||
{ | |||
return $this->getArrayElementsValue($this->glowProperties, $property); | |||
} | |||
/** | |||
* Set Glow Color | |||
* | |||
* @param float $size | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setGlowSize($size) | |||
{ | |||
if (!is_null($size)) { | |||
$this->glowProperties['size'] = $this->getExcelPointsWidth($size); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Glow Color | |||
* | |||
* @param string $color | |||
* @param int $alpha | |||
* @param string $type | |||
* | |||
* @return PHPExcel_Chart_Axis | |||
*/ | |||
private function setGlowColor($color, $alpha, $type) | |||
{ | |||
$this->glowProperties['color'] = $this->setColorProperties($color, $alpha, $type); | |||
return $this; | |||
} | |||
/** | |||
* Set Soft Edges Size | |||
* | |||
* @param float $size | |||
*/ | |||
public function setSoftEdges($size) | |||
{ | |||
if (!is_null($size)) { | |||
$softEdges['size'] = (string) $this->getExcelPointsWidth($size); | |||
} | |||
} | |||
/** | |||
* Get Soft Edges Size | |||
* | |||
* @return string | |||
*/ | |||
public function getSoftEdgesSize() | |||
{ | |||
return $this->softEdges['size']; | |||
} | |||
} |
@ -0,0 +1,390 @@ | |||
<?php | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
/** | |||
* PHPExcel_Chart_DataSeries | |||
* | |||
* @category PHPExcel | |||
* @package PHPExcel_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
*/ | |||
class PHPExcel_Chart_DataSeries | |||
{ | |||
const TYPE_BARCHART = 'barChart'; | |||
const TYPE_BARCHART_3D = 'bar3DChart'; | |||
const TYPE_LINECHART = 'lineChart'; | |||
const TYPE_LINECHART_3D = 'line3DChart'; | |||
const TYPE_AREACHART = 'areaChart'; | |||
const TYPE_AREACHART_3D = 'area3DChart'; | |||
const TYPE_PIECHART = 'pieChart'; | |||
const TYPE_PIECHART_3D = 'pie3DChart'; | |||
const TYPE_DOUGHTNUTCHART = 'doughnutChart'; | |||
const TYPE_DONUTCHART = self::TYPE_DOUGHTNUTCHART; // Synonym | |||
const TYPE_SCATTERCHART = 'scatterChart'; | |||
const TYPE_SURFACECHART = 'surfaceChart'; | |||
const TYPE_SURFACECHART_3D = 'surface3DChart'; | |||
const TYPE_RADARCHART = 'radarChart'; | |||
const TYPE_BUBBLECHART = 'bubbleChart'; | |||
const TYPE_STOCKCHART = 'stockChart'; | |||
const TYPE_CANDLECHART = self::TYPE_STOCKCHART; // Synonym | |||
const GROUPING_CLUSTERED = 'clustered'; | |||
const GROUPING_STACKED = 'stacked'; | |||
const GROUPING_PERCENT_STACKED = 'percentStacked'; | |||
const GROUPING_STANDARD = 'standard'; | |||
const DIRECTION_BAR = 'bar'; | |||
const DIRECTION_HORIZONTAL = self::DIRECTION_BAR; | |||
const DIRECTION_COL = 'col'; | |||
const DIRECTION_COLUMN = self::DIRECTION_COL; | |||
const DIRECTION_VERTICAL = self::DIRECTION_COL; | |||
const STYLE_LINEMARKER = 'lineMarker'; | |||
const STYLE_SMOOTHMARKER = 'smoothMarker'; | |||
const STYLE_MARKER = 'marker'; | |||
const STYLE_FILLED = 'filled'; | |||
/** | |||
* Series Plot Type | |||
* | |||
* @var string | |||
*/ | |||
private $plotType; | |||
/** | |||
* Plot Grouping Type | |||
* | |||
* @var boolean | |||
*/ | |||
private $plotGrouping; | |||
/** | |||
* Plot Direction | |||
* | |||
* @var boolean | |||
*/ | |||
private $plotDirection; | |||
/** | |||
* Plot Style | |||
* | |||
* @var string | |||
*/ | |||
private $plotStyle; | |||
/** | |||
* Order of plots in Series | |||
* | |||
* @var array of integer | |||
*/ | |||
private $plotOrder = array(); | |||
/** | |||
* Plot Label | |||
* | |||
* @var array of PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
private $plotLabel = array(); | |||
/** | |||
* Plot Category | |||
* | |||
* @var array of PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
private $plotCategory = array(); | |||
/** | |||
* Smooth Line | |||
* | |||
* @var string | |||
*/ | |||
private $smoothLine; | |||
/** | |||
* Plot Values | |||
* | |||
* @var array of PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
private $plotValues = array(); | |||
/** | |||
* Create a new PHPExcel_Chart_DataSeries | |||
*/ | |||
public function __construct($plotType = null, $plotGrouping = null, $plotOrder = array(), $plotLabel = array(), $plotCategory = array(), $plotValues = array(), $plotDirection = null, $smoothLine = null, $plotStyle = null) | |||
{ | |||
$this->plotType = $plotType; | |||
$this->plotGrouping = $plotGrouping; | |||
$this->plotOrder = $plotOrder; | |||
$keys = array_keys($plotValues); | |||
$this->plotValues = $plotValues; | |||
if ((count($plotLabel) == 0) || (is_null($plotLabel[$keys[0]]))) { | |||
$plotLabel[$keys[0]] = new PHPExcel_Chart_DataSeriesValues(); | |||
} | |||
$this->plotLabel = $plotLabel; | |||
if ((count($plotCategory) == 0) || (is_null($plotCategory[$keys[0]]))) { | |||
$plotCategory[$keys[0]] = new PHPExcel_Chart_DataSeriesValues(); | |||
} | |||
$this->plotCategory = $plotCategory; | |||
$this->smoothLine = $smoothLine; | |||
$this->plotStyle = $plotStyle; | |||
if (is_null($plotDirection)) { | |||
$plotDirection = self::DIRECTION_COL; | |||
} | |||
$this->plotDirection = $plotDirection; | |||
} | |||
/** | |||
* Get Plot Type | |||
* | |||
* @return string | |||
*/ | |||
public function getPlotType() | |||
{ | |||
return $this->plotType; | |||
} | |||
/** | |||
* Set Plot Type | |||
* | |||
* @param string $plotType | |||
* @return PHPExcel_Chart_DataSeries | |||
*/ | |||
public function setPlotType($plotType = '') | |||
{ | |||
$this->plotType = $plotType; | |||
return $this; | |||
} | |||
/** | |||
* Get Plot Grouping Type | |||
* | |||
* @return string | |||
*/ | |||
public function getPlotGrouping() | |||
{ | |||
return $this->plotGrouping; | |||
} | |||
/** | |||
* Set Plot Grouping Type | |||
* | |||
* @param string $groupingType | |||
* @return PHPExcel_Chart_DataSeries | |||
*/ | |||
public function setPlotGrouping($groupingType = null) | |||
{ | |||
$this->plotGrouping = $groupingType; | |||
return $this; | |||
} | |||
/** | |||
* Get Plot Direction | |||
* | |||
* @return string | |||
*/ | |||
public function getPlotDirection() | |||
{ | |||
return $this->plotDirection; | |||
} | |||
/** | |||
* Set Plot Direction | |||
* | |||
* @param string $plotDirection | |||
* @return PHPExcel_Chart_DataSeries | |||
*/ | |||
public function setPlotDirection($plotDirection = null) | |||
{ | |||
$this->plotDirection = $plotDirection; | |||
return $this; | |||
} | |||
/** | |||
* Get Plot Order | |||
* | |||
* @return string | |||
*/ | |||
public function getPlotOrder() | |||
{ | |||
return $this->plotOrder; | |||
} | |||
/** | |||
* Get Plot Labels | |||
* | |||
* @return array of PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function getPlotLabels() | |||
{ | |||
return $this->plotLabel; | |||
} | |||
/** | |||
* Get Plot Label by Index | |||
* | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function getPlotLabelByIndex($index) | |||
{ | |||
$keys = array_keys($this->plotLabel); | |||
if (in_array($index, $keys)) { | |||
return $this->plotLabel[$index]; | |||
} elseif (isset($keys[$index])) { | |||
return $this->plotLabel[$keys[$index]]; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get Plot Categories | |||
* | |||
* @return array of PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function getPlotCategories() | |||
{ | |||
return $this->plotCategory; | |||
} | |||
/** | |||
* Get Plot Category by Index | |||
* | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function getPlotCategoryByIndex($index) | |||
{ | |||
$keys = array_keys($this->plotCategory); | |||
if (in_array($index, $keys)) { | |||
return $this->plotCategory[$index]; | |||
} elseif (isset($keys[$index])) { | |||
return $this->plotCategory[$keys[$index]]; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get Plot Style | |||
* | |||
* @return string | |||
*/ | |||
public function getPlotStyle() | |||
{ | |||
return $this->plotStyle; | |||
} | |||
/** | |||
* Set Plot Style | |||
* | |||
* @param string $plotStyle | |||
* @return PHPExcel_Chart_DataSeries | |||
*/ | |||
public function setPlotStyle($plotStyle = null) | |||
{ | |||
$this->plotStyle = $plotStyle; | |||
return $this; | |||
} | |||
/** | |||
* Get Plot Values | |||
* | |||
* @return array of PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function getPlotValues() | |||
{ | |||
return $this->plotValues; | |||
} | |||
/** | |||
* Get Plot Values by Index | |||
* | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function getPlotValuesByIndex($index) | |||
{ | |||
$keys = array_keys($this->plotValues); | |||
if (in_array($index, $keys)) { | |||
return $this->plotValues[$index]; | |||
} elseif (isset($keys[$index])) { | |||
return $this->plotValues[$keys[$index]]; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get Number of Plot Series | |||
* | |||
* @return integer | |||
*/ | |||
public function getPlotSeriesCount() | |||
{ | |||
return count($this->plotValues); | |||
} | |||
/** | |||
* Get Smooth Line | |||
* | |||
* @return boolean | |||
*/ | |||
public function getSmoothLine() | |||
{ | |||
return $this->smoothLine; | |||
} | |||
/** | |||
* Set Smooth Line | |||
* | |||
* @param boolean $smoothLine | |||
* @return PHPExcel_Chart_DataSeries | |||
*/ | |||
public function setSmoothLine($smoothLine = true) | |||
{ | |||
$this->smoothLine = $smoothLine; | |||
return $this; | |||
} | |||
public function refresh(PHPExcel_Worksheet $worksheet) | |||
{ | |||
foreach ($this->plotValues as $plotValues) { | |||
if ($plotValues !== null) { | |||
$plotValues->refresh($worksheet, true); | |||
} | |||
} | |||
foreach ($this->plotLabel as $plotValues) { | |||
if ($plotValues !== null) { | |||
$plotValues->refresh($worksheet, true); | |||
} | |||
} | |||
foreach ($this->plotCategory as $plotValues) { | |||
if ($plotValues !== null) { | |||
$plotValues->refresh($worksheet, false); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,333 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Chart_DataSeriesValues | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart_DataSeriesValues | |||
{ | |||
const DATASERIES_TYPE_STRING = 'String'; | |||
const DATASERIES_TYPE_NUMBER = 'Number'; | |||
private static $dataTypeValues = array( | |||
self::DATASERIES_TYPE_STRING, | |||
self::DATASERIES_TYPE_NUMBER, | |||
); | |||
/** | |||
* Series Data Type | |||
* | |||
* @var string | |||
*/ | |||
private $dataType; | |||
/** | |||
* Series Data Source | |||
* | |||
* @var string | |||
*/ | |||
private $dataSource; | |||
/** | |||
* Format Code | |||
* | |||
* @var string | |||
*/ | |||
private $formatCode; | |||
/** | |||
* Series Point Marker | |||
* | |||
* @var string | |||
*/ | |||
private $pointMarker; | |||
/** | |||
* Point Count (The number of datapoints in the dataseries) | |||
* | |||
* @var integer | |||
*/ | |||
private $pointCount = 0; | |||
/** | |||
* Data Values | |||
* | |||
* @var array of mixed | |||
*/ | |||
private $dataValues = array(); | |||
/** | |||
* Create a new PHPExcel_Chart_DataSeriesValues object | |||
*/ | |||
public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = array(), $marker = null) | |||
{ | |||
$this->setDataType($dataType); | |||
$this->dataSource = $dataSource; | |||
$this->formatCode = $formatCode; | |||
$this->pointCount = $pointCount; | |||
$this->dataValues = $dataValues; | |||
$this->pointMarker = $marker; | |||
} | |||
/** | |||
* Get Series Data Type | |||
* | |||
* @return string | |||
*/ | |||
public function getDataType() | |||
{ | |||
return $this->dataType; | |||
} | |||
/** | |||
* Set Series Data Type | |||
* | |||
* @param string $dataType Datatype of this data series | |||
* Typical values are: | |||
* PHPExcel_Chart_DataSeriesValues::DATASERIES_TYPE_STRING | |||
* Normally used for axis point values | |||
* PHPExcel_Chart_DataSeriesValues::DATASERIES_TYPE_NUMBER | |||
* Normally used for chart data values | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function setDataType($dataType = self::DATASERIES_TYPE_NUMBER) | |||
{ | |||
if (!in_array($dataType, self::$dataTypeValues)) { | |||
throw new PHPExcel_Chart_Exception('Invalid datatype for chart data series values'); | |||
} | |||
$this->dataType = $dataType; | |||
return $this; | |||
} | |||
/** | |||
* Get Series Data Source (formula) | |||
* | |||
* @return string | |||
*/ | |||
public function getDataSource() | |||
{ | |||
return $this->dataSource; | |||
} | |||
/** | |||
* Set Series Data Source (formula) | |||
* | |||
* @param string $dataSource | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function setDataSource($dataSource = null, $refreshDataValues = true) | |||
{ | |||
$this->dataSource = $dataSource; | |||
if ($refreshDataValues) { | |||
// TO DO | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get Point Marker | |||
* | |||
* @return string | |||
*/ | |||
public function getPointMarker() | |||
{ | |||
return $this->pointMarker; | |||
} | |||
/** | |||
* Set Point Marker | |||
* | |||
* @param string $marker | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function setPointMarker($marker = null) | |||
{ | |||
$this->pointMarker = $marker; | |||
return $this; | |||
} | |||
/** | |||
* Get Series Format Code | |||
* | |||
* @return string | |||
*/ | |||
public function getFormatCode() | |||
{ | |||
return $this->formatCode; | |||
} | |||
/** | |||
* Set Series Format Code | |||
* | |||
* @param string $formatCode | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function setFormatCode($formatCode = null) | |||
{ | |||
$this->formatCode = $formatCode; | |||
return $this; | |||
} | |||
/** | |||
* Get Series Point Count | |||
* | |||
* @return integer | |||
*/ | |||
public function getPointCount() | |||
{ | |||
return $this->pointCount; | |||
} | |||
/** | |||
* Identify if the Data Series is a multi-level or a simple series | |||
* | |||
* @return boolean | |||
*/ | |||
public function isMultiLevelSeries() | |||
{ | |||
if (count($this->dataValues) > 0) { | |||
return is_array($this->dataValues[0]); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Return the level count of a multi-level Data Series | |||
* | |||
* @return boolean | |||
*/ | |||
public function multiLevelCount() | |||
{ | |||
$levelCount = 0; | |||
foreach ($this->dataValues as $dataValueSet) { | |||
$levelCount = max($levelCount, count($dataValueSet)); | |||
} | |||
return $levelCount; | |||
} | |||
/** | |||
* Get Series Data Values | |||
* | |||
* @return array of mixed | |||
*/ | |||
public function getDataValues() | |||
{ | |||
return $this->dataValues; | |||
} | |||
/** | |||
* Get the first Series Data value | |||
* | |||
* @return mixed | |||
*/ | |||
public function getDataValue() | |||
{ | |||
$count = count($this->dataValues); | |||
if ($count == 0) { | |||
return null; | |||
} elseif ($count == 1) { | |||
return $this->dataValues[0]; | |||
} | |||
return $this->dataValues; | |||
} | |||
/** | |||
* Set Series Data Values | |||
* | |||
* @param array $dataValues | |||
* @param boolean $refreshDataSource | |||
* TRUE - refresh the value of dataSource based on the values of $dataValues | |||
* FALSE - don't change the value of dataSource | |||
* @return PHPExcel_Chart_DataSeriesValues | |||
*/ | |||
public function setDataValues($dataValues = array(), $refreshDataSource = true) | |||
{ | |||
$this->dataValues = PHPExcel_Calculation_Functions::flattenArray($dataValues); | |||
$this->pointCount = count($dataValues); | |||
if ($refreshDataSource) { | |||
// TO DO | |||
} | |||
return $this; | |||
} | |||
private function stripNulls($var) | |||
{ | |||
return $var !== null; | |||
} | |||
public function refresh(PHPExcel_Worksheet $worksheet, $flatten = true) | |||
{ | |||
if ($this->dataSource !== null) { | |||
$calcEngine = PHPExcel_Calculation::getInstance($worksheet->getParent()); | |||
$newDataValues = PHPExcel_Calculation::unwrapResult( | |||
$calcEngine->_calculateFormulaValue( | |||
'='.$this->dataSource, | |||
null, | |||
$worksheet->getCell('A1') | |||
) | |||
); | |||
if ($flatten) { | |||
$this->dataValues = PHPExcel_Calculation_Functions::flattenArray($newDataValues); | |||
foreach ($this->dataValues as &$dataValue) { | |||
if ((!empty($dataValue)) && ($dataValue[0] == '#')) { | |||
$dataValue = 0.0; | |||
} | |||
} | |||
unset($dataValue); | |||
} else { | |||
$cellRange = explode('!', $this->dataSource); | |||
if (count($cellRange) > 1) { | |||
list(, $cellRange) = $cellRange; | |||
} | |||
$dimensions = PHPExcel_Cell::rangeDimension(str_replace('$', '', $cellRange)); | |||
if (($dimensions[0] == 1) || ($dimensions[1] == 1)) { | |||
$this->dataValues = PHPExcel_Calculation_Functions::flattenArray($newDataValues); | |||
} else { | |||
$newArray = array_values(array_shift($newDataValues)); | |||
foreach ($newArray as $i => $newDataSet) { | |||
$newArray[$i] = array($newDataSet); | |||
} | |||
foreach ($newDataValues as $newDataSet) { | |||
$i = 0; | |||
foreach ($newDataSet as $newDataVal) { | |||
array_unshift($newArray[$i++], $newDataVal); | |||
} | |||
} | |||
$this->dataValues = $newArray; | |||
} | |||
} | |||
$this->pointCount = count($this->dataValues); | |||
} | |||
} | |||
} |
@ -0,0 +1,46 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Chart_Exception | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart_Exception extends PHPExcel_Exception | |||
{ | |||
/** | |||
* Error handler callback | |||
* | |||
* @param mixed $code | |||
* @param mixed $string | |||
* @param mixed $file | |||
* @param mixed $line | |||
* @param mixed $context | |||
*/ | |||
public static function errorHandlerCallback($code, $string, $file, $line, $context) | |||
{ | |||
$e = new self($string, $code); | |||
$e->line = $line; | |||
$e->file = $file; | |||
throw $e; | |||
} | |||
} |
@ -0,0 +1,472 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Wiktor Trzonkowski | |||
* Date: 7/2/14 | |||
* Time: 2:36 PM | |||
*/ | |||
class PHPExcel_Chart_GridLines extends PHPExcel_Chart_Properties | |||
{ | |||
/** | |||
* Properties of Class: | |||
* Object State (State for Minor Tick Mark) @var bool | |||
* Line Properties @var array of mixed | |||
* Shadow Properties @var array of mixed | |||
* Glow Properties @var array of mixed | |||
* Soft Properties @var array of mixed | |||
* | |||
*/ | |||
private $objectState = false; | |||
private $lineProperties = array( | |||
'color' => array( | |||
'type' => self::EXCEL_COLOR_TYPE_STANDARD, | |||
'value' => null, | |||
'alpha' => 0 | |||
), | |||
'style' => array( | |||
'width' => '9525', | |||
'compound' => self::LINE_STYLE_COMPOUND_SIMPLE, | |||
'dash' => self::LINE_STYLE_DASH_SOLID, | |||
'cap' => self::LINE_STYLE_CAP_FLAT, | |||
'join' => self::LINE_STYLE_JOIN_BEVEL, | |||
'arrow' => array( | |||
'head' => array( | |||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, | |||
'size' => self::LINE_STYLE_ARROW_SIZE_5 | |||
), | |||
'end' => array( | |||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW, | |||
'size' => self::LINE_STYLE_ARROW_SIZE_8 | |||
), | |||
) | |||
) | |||
); | |||
private $shadowProperties = array( | |||
'presets' => self::SHADOW_PRESETS_NOSHADOW, | |||
'effect' => null, | |||
'color' => array( | |||
'type' => self::EXCEL_COLOR_TYPE_STANDARD, | |||
'value' => 'black', | |||
'alpha' => 85, | |||
), | |||
'size' => array( | |||
'sx' => null, | |||
'sy' => null, | |||
'kx' => null | |||
), | |||
'blur' => null, | |||
'direction' => null, | |||
'distance' => null, | |||
'algn' => null, | |||
'rotWithShape' => null | |||
); | |||
private $glowProperties = array( | |||
'size' => null, | |||
'color' => array( | |||
'type' => self::EXCEL_COLOR_TYPE_STANDARD, | |||
'value' => 'black', | |||
'alpha' => 40 | |||
) | |||
); | |||
private $softEdges = array( | |||
'size' => null | |||
); | |||
/** | |||
* Get Object State | |||
* | |||
* @return bool | |||
*/ | |||
public function getObjectState() | |||
{ | |||
return $this->objectState; | |||
} | |||
/** | |||
* Change Object State to True | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function activateObject() | |||
{ | |||
$this->objectState = true; | |||
return $this; | |||
} | |||
/** | |||
* Set Line Color Properties | |||
* | |||
* @param string $value | |||
* @param int $alpha | |||
* @param string $type | |||
*/ | |||
public function setLineColorProperties($value, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_STANDARD) | |||
{ | |||
$this->activateObject() | |||
->lineProperties['color'] = $this->setColorProperties( | |||
$value, | |||
$alpha, | |||
$type | |||
); | |||
} | |||
/** | |||
* Set Line Color Properties | |||
* | |||
* @param float $line_width | |||
* @param string $compound_type | |||
* @param string $dash_type | |||
* @param string $cap_type | |||
* @param string $join_type | |||
* @param string $head_arrow_type | |||
* @param string $head_arrow_size | |||
* @param string $end_arrow_type | |||
* @param string $end_arrow_size | |||
*/ | |||
public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null) | |||
{ | |||
$this->activateObject(); | |||
(!is_null($line_width)) | |||
? $this->lineProperties['style']['width'] = $this->getExcelPointsWidth((float) $line_width) | |||
: null; | |||
(!is_null($compound_type)) | |||
? $this->lineProperties['style']['compound'] = (string) $compound_type | |||
: null; | |||
(!is_null($dash_type)) | |||
? $this->lineProperties['style']['dash'] = (string) $dash_type | |||
: null; | |||
(!is_null($cap_type)) | |||
? $this->lineProperties['style']['cap'] = (string) $cap_type | |||
: null; | |||
(!is_null($join_type)) | |||
? $this->lineProperties['style']['join'] = (string) $join_type | |||
: null; | |||
(!is_null($head_arrow_type)) | |||
? $this->lineProperties['style']['arrow']['head']['type'] = (string) $head_arrow_type | |||
: null; | |||
(!is_null($head_arrow_size)) | |||
? $this->lineProperties['style']['arrow']['head']['size'] = (string) $head_arrow_size | |||
: null; | |||
(!is_null($end_arrow_type)) | |||
? $this->lineProperties['style']['arrow']['end']['type'] = (string) $end_arrow_type | |||
: null; | |||
(!is_null($end_arrow_size)) | |||
? $this->lineProperties['style']['arrow']['end']['size'] = (string) $end_arrow_size | |||
: null; | |||
} | |||
/** | |||
* Get Line Color Property | |||
* | |||
* @param string $parameter | |||
* | |||
* @return string | |||
*/ | |||
public function getLineColorProperty($parameter) | |||
{ | |||
return $this->lineProperties['color'][$parameter]; | |||
} | |||
/** | |||
* Get Line Style Property | |||
* | |||
* @param array|string $elements | |||
* | |||
* @return string | |||
*/ | |||
public function getLineStyleProperty($elements) | |||
{ | |||
return $this->getArrayElementsValue($this->lineProperties['style'], $elements); | |||
} | |||
/** | |||
* Set Glow Properties | |||
* | |||
* @param float $size | |||
* @param string $color_value | |||
* @param int $color_alpha | |||
* @param string $color_type | |||
* | |||
*/ | |||
public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null) | |||
{ | |||
$this | |||
->activateObject() | |||
->setGlowSize($size) | |||
->setGlowColor($color_value, $color_alpha, $color_type); | |||
} | |||
/** | |||
* Get Glow Color Property | |||
* | |||
* @param string $property | |||
* | |||
* @return string | |||
*/ | |||
public function getGlowColor($property) | |||
{ | |||
return $this->glowProperties['color'][$property]; | |||
} | |||
/** | |||
* Get Glow Size | |||
* | |||
* @return string | |||
*/ | |||
public function getGlowSize() | |||
{ | |||
return $this->glowProperties['size']; | |||
} | |||
/** | |||
* Set Glow Size | |||
* | |||
* @param float $size | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setGlowSize($size) | |||
{ | |||
$this->glowProperties['size'] = $this->getExcelPointsWidth((float) $size); | |||
return $this; | |||
} | |||
/** | |||
* Set Glow Color | |||
* | |||
* @param string $color | |||
* @param int $alpha | |||
* @param string $type | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setGlowColor($color, $alpha, $type) | |||
{ | |||
if (!is_null($color)) { | |||
$this->glowProperties['color']['value'] = (string) $color; | |||
} | |||
if (!is_null($alpha)) { | |||
$this->glowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha); | |||
} | |||
if (!is_null($type)) { | |||
$this->glowProperties['color']['type'] = (string) $type; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get Line Style Arrow Parameters | |||
* | |||
* @param string $arrow_selector | |||
* @param string $property_selector | |||
* | |||
* @return string | |||
*/ | |||
public function getLineStyleArrowParameters($arrow_selector, $property_selector) | |||
{ | |||
return $this->getLineStyleArrowSize($this->lineProperties['style']['arrow'][$arrow_selector]['size'], $property_selector); | |||
} | |||
/** | |||
* Set Shadow Properties | |||
* | |||
* @param int $sh_presets | |||
* @param string $sh_color_value | |||
* @param string $sh_color_type | |||
* @param int $sh_color_alpha | |||
* @param string $sh_blur | |||
* @param int $sh_angle | |||
* @param float $sh_distance | |||
* | |||
*/ | |||
public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null) | |||
{ | |||
$this->activateObject() | |||
->setShadowPresetsProperties((int) $sh_presets) | |||
->setShadowColor( | |||
is_null($sh_color_value) ? $this->shadowProperties['color']['value'] : $sh_color_value, | |||
is_null($sh_color_alpha) ? (int) $this->shadowProperties['color']['alpha'] : $this->getTrueAlpha($sh_color_alpha), | |||
is_null($sh_color_type) ? $this->shadowProperties['color']['type'] : $sh_color_type | |||
) | |||
->setShadowBlur($sh_blur) | |||
->setShadowAngle($sh_angle) | |||
->setShadowDistance($sh_distance); | |||
} | |||
/** | |||
* Set Shadow Presets Properties | |||
* | |||
* @param int $shadow_presets | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setShadowPresetsProperties($shadow_presets) | |||
{ | |||
$this->shadowProperties['presets'] = $shadow_presets; | |||
$this->setShadowProperiesMapValues($this->getShadowPresetsMap($shadow_presets)); | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Properties Values | |||
* | |||
* @param array $properties_map | |||
* @param * $reference | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setShadowProperiesMapValues(array $properties_map, &$reference = null) | |||
{ | |||
$base_reference = $reference; | |||
foreach ($properties_map as $property_key => $property_val) { | |||
if (is_array($property_val)) { | |||
if ($reference === null) { | |||
$reference = & $this->shadowProperties[$property_key]; | |||
} else { | |||
$reference = & $reference[$property_key]; | |||
} | |||
$this->setShadowProperiesMapValues($property_val, $reference); | |||
} else { | |||
if ($base_reference === null) { | |||
$this->shadowProperties[$property_key] = $property_val; | |||
} else { | |||
$reference[$property_key] = $property_val; | |||
} | |||
} | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Color | |||
* | |||
* @param string $color | |||
* @param int $alpha | |||
* @param string $type | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setShadowColor($color, $alpha, $type) | |||
{ | |||
if (!is_null($color)) { | |||
$this->shadowProperties['color']['value'] = (string) $color; | |||
} | |||
if (!is_null($alpha)) { | |||
$this->shadowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha); | |||
} | |||
if (!is_null($type)) { | |||
$this->shadowProperties['color']['type'] = (string) $type; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Blur | |||
* | |||
* @param float $blur | |||
* | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setShadowBlur($blur) | |||
{ | |||
if ($blur !== null) { | |||
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Angle | |||
* | |||
* @param int $angle | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setShadowAngle($angle) | |||
{ | |||
if ($angle !== null) { | |||
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Set Shadow Distance | |||
* | |||
* @param float $distance | |||
* @return PHPExcel_Chart_GridLines | |||
*/ | |||
private function setShadowDistance($distance) | |||
{ | |||
if ($distance !== null) { | |||
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get Shadow Property | |||
* | |||
* @param string $elements | |||
* @param array $elements | |||
* @return string | |||
*/ | |||
public function getShadowProperty($elements) | |||
{ | |||
return $this->getArrayElementsValue($this->shadowProperties, $elements); | |||
} | |||
/** | |||
* Set Soft Edges Size | |||
* | |||
* @param float $size | |||
*/ | |||
public function setSoftEdgesSize($size) | |||
{ | |||
if (!is_null($size)) { | |||
$this->activateObject(); | |||
$softEdges['size'] = (string) $this->getExcelPointsWidth($size); | |||
} | |||
} | |||
/** | |||
* Get Soft Edges Size | |||
* | |||
* @return string | |||
*/ | |||
public function getSoftEdgesSize() | |||
{ | |||
return $this->softEdges['size']; | |||
} | |||
} |
@ -0,0 +1,486 @@ | |||
<?php | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
/** | |||
* PHPExcel_Chart_Layout | |||
* | |||
* @category PHPExcel | |||
* @package PHPExcel_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
*/ | |||
class PHPExcel_Chart_Layout | |||
{ | |||
/** | |||
* layoutTarget | |||
* | |||
* @var string | |||
*/ | |||
private $layoutTarget; | |||
/** | |||
* X Mode | |||
* | |||
* @var string | |||
*/ | |||
private $xMode; | |||
/** | |||
* Y Mode | |||
* | |||
* @var string | |||
*/ | |||
private $yMode; | |||
/** | |||
* X-Position | |||
* | |||
* @var float | |||
*/ | |||
private $xPos; | |||
/** | |||
* Y-Position | |||
* | |||
* @var float | |||
*/ | |||
private $yPos; | |||
/** | |||
* width | |||
* | |||
* @var float | |||
*/ | |||
private $width; | |||
/** | |||
* height | |||
* | |||
* @var float | |||
*/ | |||
private $height; | |||
/** | |||
* show legend key | |||
* Specifies that legend keys should be shown in data labels | |||
* | |||
* @var boolean | |||
*/ | |||
private $showLegendKey; | |||
/** | |||
* show value | |||
* Specifies that the value should be shown in a data label. | |||
* | |||
* @var boolean | |||
*/ | |||
private $showVal; | |||
/** | |||
* show category name | |||
* Specifies that the category name should be shown in the data label. | |||
* | |||
* @var boolean | |||
*/ | |||
private $showCatName; | |||
/** | |||
* show data series name | |||
* Specifies that the series name should be shown in the data label. | |||
* | |||
* @var boolean | |||
*/ | |||
private $showSerName; | |||
/** | |||
* show percentage | |||
* Specifies that the percentage should be shown in the data label. | |||
* | |||
* @var boolean | |||
*/ | |||
private $showPercent; | |||
/** | |||
* show bubble size | |||
* | |||
* @var boolean | |||
*/ | |||
private $showBubbleSize; | |||
/** | |||
* show leader lines | |||
* Specifies that leader lines should be shown for the data label. | |||
* | |||
* @var boolean | |||
*/ | |||
private $showLeaderLines; | |||
/** | |||
* Create a new PHPExcel_Chart_Layout | |||
*/ | |||
public function __construct($layout = array()) | |||
{ | |||
if (isset($layout['layoutTarget'])) { | |||
$this->layoutTarget = $layout['layoutTarget']; | |||
} | |||
if (isset($layout['xMode'])) { | |||
$this->xMode = $layout['xMode']; | |||
} | |||
if (isset($layout['yMode'])) { | |||
$this->yMode = $layout['yMode']; | |||
} | |||
if (isset($layout['x'])) { | |||
$this->xPos = (float) $layout['x']; | |||
} | |||
if (isset($layout['y'])) { | |||
$this->yPos = (float) $layout['y']; | |||
} | |||
if (isset($layout['w'])) { | |||
$this->width = (float) $layout['w']; | |||
} | |||
if (isset($layout['h'])) { | |||
$this->height = (float) $layout['h']; | |||
} | |||
} | |||
/** | |||
* Get Layout Target | |||
* | |||
* @return string | |||
*/ | |||
public function getLayoutTarget() | |||
{ | |||
return $this->layoutTarget; | |||
} | |||
/** | |||
* Set Layout Target | |||
* | |||
* @param Layout Target $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setLayoutTarget($value) | |||
{ | |||
$this->layoutTarget = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get X-Mode | |||
* | |||
* @return string | |||
*/ | |||
public function getXMode() | |||
{ | |||
return $this->xMode; | |||
} | |||
/** | |||
* Set X-Mode | |||
* | |||
* @param X-Mode $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setXMode($value) | |||
{ | |||
$this->xMode = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Y-Mode | |||
* | |||
* @return string | |||
*/ | |||
public function getYMode() | |||
{ | |||
return $this->yMode; | |||
} | |||
/** | |||
* Set Y-Mode | |||
* | |||
* @param Y-Mode $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setYMode($value) | |||
{ | |||
$this->yMode = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get X-Position | |||
* | |||
* @return number | |||
*/ | |||
public function getXPosition() | |||
{ | |||
return $this->xPos; | |||
} | |||
/** | |||
* Set X-Position | |||
* | |||
* @param X-Position $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setXPosition($value) | |||
{ | |||
$this->xPos = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Y-Position | |||
* | |||
* @return number | |||
*/ | |||
public function getYPosition() | |||
{ | |||
return $this->yPos; | |||
} | |||
/** | |||
* Set Y-Position | |||
* | |||
* @param Y-Position $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setYPosition($value) | |||
{ | |||
$this->yPos = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Width | |||
* | |||
* @return number | |||
*/ | |||
public function getWidth() | |||
{ | |||
return $this->width; | |||
} | |||
/** | |||
* Set Width | |||
* | |||
* @param Width $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setWidth($value) | |||
{ | |||
$this->width = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get Height | |||
* | |||
* @return number | |||
*/ | |||
public function getHeight() | |||
{ | |||
return $this->height; | |||
} | |||
/** | |||
* Set Height | |||
* | |||
* @param Height $value | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setHeight($value) | |||
{ | |||
$this->height = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show legend key | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowLegendKey() | |||
{ | |||
return $this->showLegendKey; | |||
} | |||
/** | |||
* Set show legend key | |||
* Specifies that legend keys should be shown in data labels. | |||
* | |||
* @param boolean $value Show legend key | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowLegendKey($value) | |||
{ | |||
$this->showLegendKey = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show value | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowVal() | |||
{ | |||
return $this->showVal; | |||
} | |||
/** | |||
* Set show val | |||
* Specifies that the value should be shown in data labels. | |||
* | |||
* @param boolean $value Show val | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowVal($value) | |||
{ | |||
$this->showVal = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show category name | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowCatName() | |||
{ | |||
return $this->showCatName; | |||
} | |||
/** | |||
* Set show cat name | |||
* Specifies that the category name should be shown in data labels. | |||
* | |||
* @param boolean $value Show cat name | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowCatName($value) | |||
{ | |||
$this->showCatName = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show data series name | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowSerName() | |||
{ | |||
return $this->showSerName; | |||
} | |||
/** | |||
* Set show ser name | |||
* Specifies that the series name should be shown in data labels. | |||
* | |||
* @param boolean $value Show series name | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowSerName($value) | |||
{ | |||
$this->showSerName = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show percentage | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowPercent() | |||
{ | |||
return $this->showPercent; | |||
} | |||
/** | |||
* Set show percentage | |||
* Specifies that the percentage should be shown in data labels. | |||
* | |||
* @param boolean $value Show percentage | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowPercent($value) | |||
{ | |||
$this->showPercent = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show bubble size | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowBubbleSize() | |||
{ | |||
return $this->showBubbleSize; | |||
} | |||
/** | |||
* Set show bubble size | |||
* Specifies that the bubble size should be shown in data labels. | |||
* | |||
* @param boolean $value Show bubble size | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowBubbleSize($value) | |||
{ | |||
$this->showBubbleSize = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get show leader lines | |||
* | |||
* @return boolean | |||
*/ | |||
public function getShowLeaderLines() | |||
{ | |||
return $this->showLeaderLines; | |||
} | |||
/** | |||
* Set show leader lines | |||
* Specifies that leader lines should be shown in data labels. | |||
* | |||
* @param boolean $value Show leader lines | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function setShowLeaderLines($value) | |||
{ | |||
$this->showLeaderLines = $value; | |||
return $this; | |||
} | |||
} |
@ -0,0 +1,170 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Chart_Legend | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart_Legend | |||
{ | |||
/** Legend positions */ | |||
const xlLegendPositionBottom = -4107; // Below the chart. | |||
const xlLegendPositionCorner = 2; // In the upper right-hand corner of the chart border. | |||
const xlLegendPositionCustom = -4161; // A custom position. | |||
const xlLegendPositionLeft = -4131; // Left of the chart. | |||
const xlLegendPositionRight = -4152; // Right of the chart. | |||
const xlLegendPositionTop = -4160; // Above the chart. | |||
const POSITION_RIGHT = 'r'; | |||
const POSITION_LEFT = 'l'; | |||
const POSITION_BOTTOM = 'b'; | |||
const POSITION_TOP = 't'; | |||
const POSITION_TOPRIGHT = 'tr'; | |||
private static $positionXLref = array( | |||
self::xlLegendPositionBottom => self::POSITION_BOTTOM, | |||
self::xlLegendPositionCorner => self::POSITION_TOPRIGHT, | |||
self::xlLegendPositionCustom => '??', | |||
self::xlLegendPositionLeft => self::POSITION_LEFT, | |||
self::xlLegendPositionRight => self::POSITION_RIGHT, | |||
self::xlLegendPositionTop => self::POSITION_TOP | |||
); | |||
/** | |||
* Legend position | |||
* | |||
* @var string | |||
*/ | |||
private $position = self::POSITION_RIGHT; | |||
/** | |||
* Allow overlay of other elements? | |||
* | |||
* @var boolean | |||
*/ | |||
private $overlay = true; | |||
/** | |||
* Legend Layout | |||
* | |||
* @var PHPExcel_Chart_Layout | |||
*/ | |||
private $layout = null; | |||
/** | |||
* Create a new PHPExcel_Chart_Legend | |||
*/ | |||
public function __construct($position = self::POSITION_RIGHT, PHPExcel_Chart_Layout $layout = null, $overlay = false) | |||
{ | |||
$this->setPosition($position); | |||
$this->layout = $layout; | |||
$this->setOverlay($overlay); | |||
} | |||
/** | |||
* Get legend position as an excel string value | |||
* | |||
* @return string | |||
*/ | |||
public function getPosition() | |||
{ | |||
return $this->position; | |||
} | |||
/** | |||
* Get legend position using an excel string value | |||
* | |||
* @param string $position | |||
*/ | |||
public function setPosition($position = self::POSITION_RIGHT) | |||
{ | |||
if (!in_array($position, self::$positionXLref)) { | |||
return false; | |||
} | |||
$this->position = $position; | |||
return true; | |||
} | |||
/** | |||
* Get legend position as an Excel internal numeric value | |||
* | |||
* @return number | |||
*/ | |||
public function getPositionXL() | |||
{ | |||
return array_search($this->position, self::$positionXLref); | |||
} | |||
/** | |||
* Set legend position using an Excel internal numeric value | |||
* | |||
* @param number $positionXL | |||
*/ | |||
public function setPositionXL($positionXL = self::xlLegendPositionRight) | |||
{ | |||
if (!array_key_exists($positionXL, self::$positionXLref)) { | |||
return false; | |||
} | |||
$this->position = self::$positionXLref[$positionXL]; | |||
return true; | |||
} | |||
/** | |||
* Get allow overlay of other elements? | |||
* | |||
* @return boolean | |||
*/ | |||
public function getOverlay() | |||
{ | |||
return $this->overlay; | |||
} | |||
/** | |||
* Set allow overlay of other elements? | |||
* | |||
* @param boolean $overlay | |||
* @return boolean | |||
*/ | |||
public function setOverlay($overlay = false) | |||
{ | |||
if (!is_bool($overlay)) { | |||
return false; | |||
} | |||
$this->overlay = $overlay; | |||
return true; | |||
} | |||
/** | |||
* Get Layout | |||
* | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function getLayout() | |||
{ | |||
return $this->layout; | |||
} | |||
} |
@ -0,0 +1,126 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Chart_PlotArea | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart_PlotArea | |||
{ | |||
/** | |||
* PlotArea Layout | |||
* | |||
* @var PHPExcel_Chart_Layout | |||
*/ | |||
private $layout = null; | |||
/** | |||
* Plot Series | |||
* | |||
* @var array of PHPExcel_Chart_DataSeries | |||
*/ | |||
private $plotSeries = array(); | |||
/** | |||
* Create a new PHPExcel_Chart_PlotArea | |||
*/ | |||
public function __construct(PHPExcel_Chart_Layout $layout = null, $plotSeries = array()) | |||
{ | |||
$this->layout = $layout; | |||
$this->plotSeries = $plotSeries; | |||
} | |||
/** | |||
* Get Layout | |||
* | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function getLayout() | |||
{ | |||
return $this->layout; | |||
} | |||
/** | |||
* Get Number of Plot Groups | |||
* | |||
* @return array of PHPExcel_Chart_DataSeries | |||
*/ | |||
public function getPlotGroupCount() | |||
{ | |||
return count($this->plotSeries); | |||
} | |||
/** | |||
* Get Number of Plot Series | |||
* | |||
* @return integer | |||
*/ | |||
public function getPlotSeriesCount() | |||
{ | |||
$seriesCount = 0; | |||
foreach ($this->plotSeries as $plot) { | |||
$seriesCount += $plot->getPlotSeriesCount(); | |||
} | |||
return $seriesCount; | |||
} | |||
/** | |||
* Get Plot Series | |||
* | |||
* @return array of PHPExcel_Chart_DataSeries | |||
*/ | |||
public function getPlotGroup() | |||
{ | |||
return $this->plotSeries; | |||
} | |||
/** | |||
* Get Plot Series by Index | |||
* | |||
* @return PHPExcel_Chart_DataSeries | |||
*/ | |||
public function getPlotGroupByIndex($index) | |||
{ | |||
return $this->plotSeries[$index]; | |||
} | |||
/** | |||
* Set Plot Series | |||
* | |||
* @param [PHPExcel_Chart_DataSeries] | |||
* @return PHPExcel_Chart_PlotArea | |||
*/ | |||
public function setPlotSeries($plotSeries = array()) | |||
{ | |||
$this->plotSeries = $plotSeries; | |||
return $this; | |||
} | |||
public function refresh(PHPExcel_Worksheet $worksheet) | |||
{ | |||
foreach ($this->plotSeries as $plotSeries) { | |||
$plotSeries->refresh($worksheet); | |||
} | |||
} | |||
} |
@ -0,0 +1,363 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: nhw2h8s | |||
* Date: 7/2/14 | |||
* Time: 5:45 PM | |||
*/ | |||
abstract class PHPExcel_Chart_Properties | |||
{ | |||
const | |||
EXCEL_COLOR_TYPE_STANDARD = 'prstClr', | |||
EXCEL_COLOR_TYPE_SCHEME = 'schemeClr', | |||
EXCEL_COLOR_TYPE_ARGB = 'srgbClr'; | |||
const | |||
AXIS_LABELS_LOW = 'low', | |||
AXIS_LABELS_HIGH = 'high', | |||
AXIS_LABELS_NEXT_TO = 'nextTo', | |||
AXIS_LABELS_NONE = 'none'; | |||
const | |||
TICK_MARK_NONE = 'none', | |||
TICK_MARK_INSIDE = 'in', | |||
TICK_MARK_OUTSIDE = 'out', | |||
TICK_MARK_CROSS = 'cross'; | |||
const | |||
HORIZONTAL_CROSSES_AUTOZERO = 'autoZero', | |||
HORIZONTAL_CROSSES_MAXIMUM = 'max'; | |||
const | |||
FORMAT_CODE_GENERAL = 'General', | |||
FORMAT_CODE_NUMBER = '#,##0.00', | |||
FORMAT_CODE_CURRENCY = '$#,##0.00', | |||
FORMAT_CODE_ACCOUNTING = '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)', | |||
FORMAT_CODE_DATE = 'm/d/yyyy', | |||
FORMAT_CODE_TIME = '[$-F400]h:mm:ss AM/PM', | |||
FORMAT_CODE_PERCENTAGE = '0.00%', | |||
FORMAT_CODE_FRACTION = '# ?/?', | |||
FORMAT_CODE_SCIENTIFIC = '0.00E+00', | |||
FORMAT_CODE_TEXT = '@', | |||
FORMAT_CODE_SPECIAL = '00000'; | |||
const | |||
ORIENTATION_NORMAL = 'minMax', | |||
ORIENTATION_REVERSED = 'maxMin'; | |||
const | |||
LINE_STYLE_COMPOUND_SIMPLE = 'sng', | |||
LINE_STYLE_COMPOUND_DOUBLE = 'dbl', | |||
LINE_STYLE_COMPOUND_THICKTHIN = 'thickThin', | |||
LINE_STYLE_COMPOUND_THINTHICK = 'thinThick', | |||
LINE_STYLE_COMPOUND_TRIPLE = 'tri', | |||
LINE_STYLE_DASH_SOLID = 'solid', | |||
LINE_STYLE_DASH_ROUND_DOT = 'sysDot', | |||
LINE_STYLE_DASH_SQUERE_DOT = 'sysDash', | |||
LINE_STYPE_DASH_DASH = 'dash', | |||
LINE_STYLE_DASH_DASH_DOT = 'dashDot', | |||
LINE_STYLE_DASH_LONG_DASH = 'lgDash', | |||
LINE_STYLE_DASH_LONG_DASH_DOT = 'lgDashDot', | |||
LINE_STYLE_DASH_LONG_DASH_DOT_DOT = 'lgDashDotDot', | |||
LINE_STYLE_CAP_SQUARE = 'sq', | |||
LINE_STYLE_CAP_ROUND = 'rnd', | |||
LINE_STYLE_CAP_FLAT = 'flat', | |||
LINE_STYLE_JOIN_ROUND = 'bevel', | |||
LINE_STYLE_JOIN_MITER = 'miter', | |||
LINE_STYLE_JOIN_BEVEL = 'bevel', | |||
LINE_STYLE_ARROW_TYPE_NOARROW = null, | |||
LINE_STYLE_ARROW_TYPE_ARROW = 'triangle', | |||
LINE_STYLE_ARROW_TYPE_OPEN = 'arrow', | |||
LINE_STYLE_ARROW_TYPE_STEALTH = 'stealth', | |||
LINE_STYLE_ARROW_TYPE_DIAMOND = 'diamond', | |||
LINE_STYLE_ARROW_TYPE_OVAL = 'oval', | |||
LINE_STYLE_ARROW_SIZE_1 = 1, | |||
LINE_STYLE_ARROW_SIZE_2 = 2, | |||
LINE_STYLE_ARROW_SIZE_3 = 3, | |||
LINE_STYLE_ARROW_SIZE_4 = 4, | |||
LINE_STYLE_ARROW_SIZE_5 = 5, | |||
LINE_STYLE_ARROW_SIZE_6 = 6, | |||
LINE_STYLE_ARROW_SIZE_7 = 7, | |||
LINE_STYLE_ARROW_SIZE_8 = 8, | |||
LINE_STYLE_ARROW_SIZE_9 = 9; | |||
const | |||
SHADOW_PRESETS_NOSHADOW = null, | |||
SHADOW_PRESETS_OUTER_BOTTTOM_RIGHT = 1, | |||
SHADOW_PRESETS_OUTER_BOTTOM = 2, | |||
SHADOW_PRESETS_OUTER_BOTTOM_LEFT = 3, | |||
SHADOW_PRESETS_OUTER_RIGHT = 4, | |||
SHADOW_PRESETS_OUTER_CENTER = 5, | |||
SHADOW_PRESETS_OUTER_LEFT = 6, | |||
SHADOW_PRESETS_OUTER_TOP_RIGHT = 7, | |||
SHADOW_PRESETS_OUTER_TOP = 8, | |||
SHADOW_PRESETS_OUTER_TOP_LEFT = 9, | |||
SHADOW_PRESETS_INNER_BOTTTOM_RIGHT = 10, | |||
SHADOW_PRESETS_INNER_BOTTOM = 11, | |||
SHADOW_PRESETS_INNER_BOTTOM_LEFT = 12, | |||
SHADOW_PRESETS_INNER_RIGHT = 13, | |||
SHADOW_PRESETS_INNER_CENTER = 14, | |||
SHADOW_PRESETS_INNER_LEFT = 15, | |||
SHADOW_PRESETS_INNER_TOP_RIGHT = 16, | |||
SHADOW_PRESETS_INNER_TOP = 17, | |||
SHADOW_PRESETS_INNER_TOP_LEFT = 18, | |||
SHADOW_PRESETS_PERSPECTIVE_BELOW = 19, | |||
SHADOW_PRESETS_PERSPECTIVE_UPPER_RIGHT = 20, | |||
SHADOW_PRESETS_PERSPECTIVE_UPPER_LEFT = 21, | |||
SHADOW_PRESETS_PERSPECTIVE_LOWER_RIGHT = 22, | |||
SHADOW_PRESETS_PERSPECTIVE_LOWER_LEFT = 23; | |||
protected function getExcelPointsWidth($width) | |||
{ | |||
return $width * 12700; | |||
} | |||
protected function getExcelPointsAngle($angle) | |||
{ | |||
return $angle * 60000; | |||
} | |||
protected function getTrueAlpha($alpha) | |||
{ | |||
return (string) 100 - $alpha . '000'; | |||
} | |||
protected function setColorProperties($color, $alpha, $type) | |||
{ | |||
return array( | |||
'type' => (string) $type, | |||
'value' => (string) $color, | |||
'alpha' => (string) $this->getTrueAlpha($alpha) | |||
); | |||
} | |||
protected function getLineStyleArrowSize($array_selector, $array_kay_selector) | |||
{ | |||
$sizes = array( | |||
1 => array('w' => 'sm', 'len' => 'sm'), | |||
2 => array('w' => 'sm', 'len' => 'med'), | |||
3 => array('w' => 'sm', 'len' => 'lg'), | |||
4 => array('w' => 'med', 'len' => 'sm'), | |||
5 => array('w' => 'med', 'len' => 'med'), | |||
6 => array('w' => 'med', 'len' => 'lg'), | |||
7 => array('w' => 'lg', 'len' => 'sm'), | |||
8 => array('w' => 'lg', 'len' => 'med'), | |||
9 => array('w' => 'lg', 'len' => 'lg') | |||
); | |||
return $sizes[$array_selector][$array_kay_selector]; | |||
} | |||
protected function getShadowPresetsMap($shadow_presets_option) | |||
{ | |||
$presets_options = array( | |||
//OUTER | |||
1 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '2700000', | |||
'algn' => 'tl', | |||
'rotWithShape' => '0' | |||
), | |||
2 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '5400000', | |||
'algn' => 't', | |||
'rotWithShape' => '0' | |||
), | |||
3 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '8100000', | |||
'algn' => 'tr', | |||
'rotWithShape' => '0' | |||
), | |||
4 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'algn' => 'l', | |||
'rotWithShape' => '0' | |||
), | |||
5 => array( | |||
'effect' => 'outerShdw', | |||
'size' => array( | |||
'sx' => '102000', | |||
'sy' => '102000' | |||
) | |||
, | |||
'blur' => '63500', | |||
'distance' => '38100', | |||
'algn' => 'ctr', | |||
'rotWithShape' => '0' | |||
), | |||
6 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '10800000', | |||
'algn' => 'r', | |||
'rotWithShape' => '0' | |||
), | |||
7 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '18900000', | |||
'algn' => 'bl', | |||
'rotWithShape' => '0' | |||
), | |||
8 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '16200000', | |||
'rotWithShape' => '0' | |||
), | |||
9 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '50800', | |||
'distance' => '38100', | |||
'direction' => '13500000', | |||
'algn' => 'br', | |||
'rotWithShape' => '0' | |||
), | |||
//INNER | |||
10 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '2700000', | |||
), | |||
11 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '5400000', | |||
), | |||
12 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '8100000', | |||
), | |||
13 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
), | |||
14 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '114300', | |||
), | |||
15 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '10800000', | |||
), | |||
16 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '18900000', | |||
), | |||
17 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '16200000', | |||
), | |||
18 => array( | |||
'effect' => 'innerShdw', | |||
'blur' => '63500', | |||
'distance' => '50800', | |||
'direction' => '13500000', | |||
), | |||
//perspective | |||
19 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '152400', | |||
'distance' => '317500', | |||
'size' => array( | |||
'sx' => '90000', | |||
'sy' => '-19000', | |||
), | |||
'direction' => '5400000', | |||
'rotWithShape' => '0', | |||
), | |||
20 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '76200', | |||
'direction' => '18900000', | |||
'size' => array( | |||
'sy' => '23000', | |||
'kx' => '-1200000', | |||
), | |||
'algn' => 'bl', | |||
'rotWithShape' => '0', | |||
), | |||
21 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '76200', | |||
'direction' => '13500000', | |||
'size' => array( | |||
'sy' => '23000', | |||
'kx' => '1200000', | |||
), | |||
'algn' => 'br', | |||
'rotWithShape' => '0', | |||
), | |||
22 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '76200', | |||
'distance' => '12700', | |||
'direction' => '2700000', | |||
'size' => array( | |||
'sy' => '-23000', | |||
'kx' => '-800400', | |||
), | |||
'algn' => 'bl', | |||
'rotWithShape' => '0', | |||
), | |||
23 => array( | |||
'effect' => 'outerShdw', | |||
'blur' => '76200', | |||
'distance' => '12700', | |||
'direction' => '8100000', | |||
'size' => array( | |||
'sy' => '-23000', | |||
'kx' => '800400', | |||
), | |||
'algn' => 'br', | |||
'rotWithShape' => '0', | |||
), | |||
); | |||
return $presets_options[$shadow_presets_option]; | |||
} | |||
protected function getArrayElementsValue($properties, $elements) | |||
{ | |||
$reference = & $properties; | |||
if (!is_array($elements)) { | |||
return $reference[$elements]; | |||
} else { | |||
foreach ($elements as $keys) { | |||
$reference = & $reference[$keys]; | |||
} | |||
return $reference; | |||
} | |||
return $this; | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
ChartDirector | |||
http://www.advsofteng.com/cdphp.html | |||
GraPHPite | |||
http://graphpite.sourceforge.net/ | |||
JpGraph | |||
http://www.aditus.nu/jpgraph/ | |||
LibChart | |||
http://naku.dohcrew.com/libchart/pages/introduction/ | |||
pChart | |||
http://pchart.sourceforge.net/ | |||
TeeChart | |||
http://www.steema.com/products/teechart/overview.html | |||
PHPGraphLib | |||
http://www.ebrueggeman.com/phpgraphlib |
@ -0,0 +1,883 @@ | |||
<?php | |||
require_once(PHPExcel_Settings::getChartRendererPath().'/jpgraph.php'); | |||
/** | |||
* PHPExcel_Chart_Renderer_jpgraph | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart_Renderer | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart_Renderer_jpgraph | |||
{ | |||
private static $width = 640; | |||
private static $height = 480; | |||
private static $colourSet = array( | |||
'mediumpurple1', 'palegreen3', 'gold1', 'cadetblue1', | |||
'darkmagenta', 'coral', 'dodgerblue3', 'eggplant', | |||
'mediumblue', 'magenta', 'sandybrown', 'cyan', | |||
'firebrick1', 'forestgreen', 'deeppink4', 'darkolivegreen', | |||
'goldenrod2' | |||
); | |||
private static $markSet = array( | |||
'diamond' => MARK_DIAMOND, | |||
'square' => MARK_SQUARE, | |||
'triangle' => MARK_UTRIANGLE, | |||
'x' => MARK_X, | |||
'star' => MARK_STAR, | |||
'dot' => MARK_FILLEDCIRCLE, | |||
'dash' => MARK_DTRIANGLE, | |||
'circle' => MARK_CIRCLE, | |||
'plus' => MARK_CROSS | |||
); | |||
private $chart; | |||
private $graph; | |||
private static $plotColour = 0; | |||
private static $plotMark = 0; | |||
private function formatPointMarker($seriesPlot, $markerID) | |||
{ | |||
$plotMarkKeys = array_keys(self::$markSet); | |||
if (is_null($markerID)) { | |||
// Use default plot marker (next marker in the series) | |||
self::$plotMark %= count(self::$markSet); | |||
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]); | |||
} elseif ($markerID !== 'none') { | |||
// Use specified plot marker (if it exists) | |||
if (isset(self::$markSet[$markerID])) { | |||
$seriesPlot->mark->SetType(self::$markSet[$markerID]); | |||
} else { | |||
// If the specified plot marker doesn't exist, use default plot marker (next marker in the series) | |||
self::$plotMark %= count(self::$markSet); | |||
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]); | |||
} | |||
} else { | |||
// Hide plot marker | |||
$seriesPlot->mark->Hide(); | |||
} | |||
$seriesPlot->mark->SetColor(self::$colourSet[self::$plotColour]); | |||
$seriesPlot->mark->SetFillColor(self::$colourSet[self::$plotColour]); | |||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); | |||
return $seriesPlot; | |||
} | |||
private function formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '') | |||
{ | |||
$datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode(); | |||
if (!is_null($datasetLabelFormatCode)) { | |||
// Retrieve any label formatting code | |||
$datasetLabelFormatCode = stripslashes($datasetLabelFormatCode); | |||
} | |||
$testCurrentIndex = 0; | |||
foreach ($datasetLabels as $i => $datasetLabel) { | |||
if (is_array($datasetLabel)) { | |||
if ($rotation == 'bar') { | |||
$datasetLabels[$i] = implode(" ", $datasetLabel); | |||
} else { | |||
$datasetLabel = array_reverse($datasetLabel); | |||
$datasetLabels[$i] = implode("\n", $datasetLabel); | |||
} | |||
} else { | |||
// Format labels according to any formatting code | |||
if (!is_null($datasetLabelFormatCode)) { | |||
$datasetLabels[$i] = PHPExcel_Style_NumberFormat::toFormattedString($datasetLabel, $datasetLabelFormatCode); | |||
} | |||
} | |||
++$testCurrentIndex; | |||
} | |||
return $datasetLabels; | |||
} | |||
private function percentageSumCalculation($groupID, $seriesCount) | |||
{ | |||
// Adjust our values to a percentage value across all series in the group | |||
for ($i = 0; $i < $seriesCount; ++$i) { | |||
if ($i == 0) { | |||
$sumValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); | |||
} else { | |||
$nextValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); | |||
foreach ($nextValues as $k => $value) { | |||
if (isset($sumValues[$k])) { | |||
$sumValues[$k] += $value; | |||
} else { | |||
$sumValues[$k] = $value; | |||
} | |||
} | |||
} | |||
} | |||
return $sumValues; | |||
} | |||
private function percentageAdjustValues($dataValues, $sumValues) | |||
{ | |||
foreach ($dataValues as $k => $dataValue) { | |||
$dataValues[$k] = $dataValue / $sumValues[$k] * 100; | |||
} | |||
return $dataValues; | |||
} | |||
private function getCaption($captionElement) | |||
{ | |||
// Read any caption | |||
$caption = (!is_null($captionElement)) ? $captionElement->getCaption() : null; | |||
// Test if we have a title caption to display | |||
if (!is_null($caption)) { | |||
// If we do, it could be a plain string or an array | |||
if (is_array($caption)) { | |||
// Implode an array to a plain string | |||
$caption = implode('', $caption); | |||
} | |||
} | |||
return $caption; | |||
} | |||
private function renderTitle() | |||
{ | |||
$title = $this->getCaption($this->chart->getTitle()); | |||
if (!is_null($title)) { | |||
$this->graph->title->Set($title); | |||
} | |||
} | |||
private function renderLegend() | |||
{ | |||
$legend = $this->chart->getLegend(); | |||
if (!is_null($legend)) { | |||
$legendPosition = $legend->getPosition(); | |||
$legendOverlay = $legend->getOverlay(); | |||
switch ($legendPosition) { | |||
case 'r': | |||
$this->graph->legend->SetPos(0.01, 0.5, 'right', 'center'); // right | |||
$this->graph->legend->SetColumns(1); | |||
break; | |||
case 'l': | |||
$this->graph->legend->SetPos(0.01, 0.5, 'left', 'center'); // left | |||
$this->graph->legend->SetColumns(1); | |||
break; | |||
case 't': | |||
$this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); // top | |||
break; | |||
case 'b': | |||
$this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); // bottom | |||
break; | |||
default: | |||
$this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); // top-right | |||
$this->graph->legend->SetColumns(1); | |||
break; | |||
} | |||
} else { | |||
$this->graph->legend->Hide(); | |||
} | |||
} | |||
private function renderCartesianPlotArea($type = 'textlin') | |||
{ | |||
$this->graph = new Graph(self::$width, self::$height); | |||
$this->graph->SetScale($type); | |||
$this->renderTitle(); | |||
// Rotate for bar rather than column chart | |||
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection(); | |||
$reverse = ($rotation == 'bar') ? true : false; | |||
$xAxisLabel = $this->chart->getXAxisLabel(); | |||
if (!is_null($xAxisLabel)) { | |||
$title = $this->getCaption($xAxisLabel); | |||
if (!is_null($title)) { | |||
$this->graph->xaxis->SetTitle($title, 'center'); | |||
$this->graph->xaxis->title->SetMargin(35); | |||
if ($reverse) { | |||
$this->graph->xaxis->title->SetAngle(90); | |||
$this->graph->xaxis->title->SetMargin(90); | |||
} | |||
} | |||
} | |||
$yAxisLabel = $this->chart->getYAxisLabel(); | |||
if (!is_null($yAxisLabel)) { | |||
$title = $this->getCaption($yAxisLabel); | |||
if (!is_null($title)) { | |||
$this->graph->yaxis->SetTitle($title, 'center'); | |||
if ($reverse) { | |||
$this->graph->yaxis->title->SetAngle(0); | |||
$this->graph->yaxis->title->SetMargin(-55); | |||
} | |||
} | |||
} | |||
} | |||
private function renderPiePlotArea($doughnut = false) | |||
{ | |||
$this->graph = new PieGraph(self::$width, self::$height); | |||
$this->renderTitle(); | |||
} | |||
private function renderRadarPlotArea() | |||
{ | |||
$this->graph = new RadarGraph(self::$width, self::$height); | |||
$this->graph->SetScale('lin'); | |||
$this->renderTitle(); | |||
} | |||
private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d') | |||
{ | |||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); | |||
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); | |||
if ($labelCount > 0) { | |||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); | |||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); | |||
$this->graph->xaxis->SetTickLabels($datasetLabels); | |||
} | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$seriesPlots = array(); | |||
if ($grouping == 'percentStacked') { | |||
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount); | |||
} | |||
// Loop through each data series in turn | |||
for ($i = 0; $i < $seriesCount; ++$i) { | |||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); | |||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); | |||
if ($grouping == 'percentStacked') { | |||
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues); | |||
} | |||
// Fill in any missing values in the $dataValues array | |||
$testCurrentIndex = 0; | |||
foreach ($dataValues as $k => $dataValue) { | |||
while ($k != $testCurrentIndex) { | |||
$dataValues[$testCurrentIndex] = null; | |||
++$testCurrentIndex; | |||
} | |||
++$testCurrentIndex; | |||
} | |||
$seriesPlot = new LinePlot($dataValues); | |||
if ($combination) { | |||
$seriesPlot->SetBarCenter(); | |||
} | |||
if ($filled) { | |||
$seriesPlot->SetFilled(true); | |||
$seriesPlot->SetColor('black'); | |||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]); | |||
} else { | |||
// Set the appropriate plot marker | |||
$this->formatPointMarker($seriesPlot, $marker); | |||
} | |||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); | |||
$seriesPlot->SetLegend($dataLabel); | |||
$seriesPlots[] = $seriesPlot; | |||
} | |||
if ($grouping == 'standard') { | |||
$groupPlot = $seriesPlots; | |||
} else { | |||
$groupPlot = new AccLinePlot($seriesPlots); | |||
} | |||
$this->graph->Add($groupPlot); | |||
} | |||
private function renderPlotBar($groupID, $dimensions = '2d') | |||
{ | |||
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection(); | |||
// Rotate for bar rather than column chart | |||
if (($groupID == 0) && ($rotation == 'bar')) { | |||
$this->graph->Set90AndMargin(); | |||
} | |||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); | |||
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); | |||
if ($labelCount > 0) { | |||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); | |||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation); | |||
// Rotate for bar rather than column chart | |||
if ($rotation == 'bar') { | |||
$datasetLabels = array_reverse($datasetLabels); | |||
$this->graph->yaxis->SetPos('max'); | |||
$this->graph->yaxis->SetLabelAlign('center', 'top'); | |||
$this->graph->yaxis->SetLabelSide(SIDE_RIGHT); | |||
} | |||
$this->graph->xaxis->SetTickLabels($datasetLabels); | |||
} | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$seriesPlots = array(); | |||
if ($grouping == 'percentStacked') { | |||
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount); | |||
} | |||
// Loop through each data series in turn | |||
for ($j = 0; $j < $seriesCount; ++$j) { | |||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues(); | |||
if ($grouping == 'percentStacked') { | |||
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues); | |||
} | |||
// Fill in any missing values in the $dataValues array | |||
$testCurrentIndex = 0; | |||
foreach ($dataValues as $k => $dataValue) { | |||
while ($k != $testCurrentIndex) { | |||
$dataValues[$testCurrentIndex] = null; | |||
++$testCurrentIndex; | |||
} | |||
++$testCurrentIndex; | |||
} | |||
// Reverse the $dataValues order for bar rather than column chart | |||
if ($rotation == 'bar') { | |||
$dataValues = array_reverse($dataValues); | |||
} | |||
$seriesPlot = new BarPlot($dataValues); | |||
$seriesPlot->SetColor('black'); | |||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]); | |||
if ($dimensions == '3d') { | |||
$seriesPlot->SetShadow(); | |||
} | |||
if (!$this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) { | |||
$dataLabel = ''; | |||
} else { | |||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue(); | |||
} | |||
$seriesPlot->SetLegend($dataLabel); | |||
$seriesPlots[] = $seriesPlot; | |||
} | |||
// Reverse the plot order for bar rather than column chart | |||
if (($rotation == 'bar') && (!($grouping == 'percentStacked'))) { | |||
$seriesPlots = array_reverse($seriesPlots); | |||
} | |||
if ($grouping == 'clustered') { | |||
$groupPlot = new GroupBarPlot($seriesPlots); | |||
} elseif ($grouping == 'standard') { | |||
$groupPlot = new GroupBarPlot($seriesPlots); | |||
} else { | |||
$groupPlot = new AccBarPlot($seriesPlots); | |||
if ($dimensions == '3d') { | |||
$groupPlot->SetShadow(); | |||
} | |||
} | |||
$this->graph->Add($groupPlot); | |||
} | |||
private function renderPlotScatter($groupID, $bubble) | |||
{ | |||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); | |||
$scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$seriesPlots = array(); | |||
// Loop through each data series in turn | |||
for ($i = 0; $i < $seriesCount; ++$i) { | |||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); | |||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); | |||
foreach ($dataValuesY as $k => $dataValueY) { | |||
$dataValuesY[$k] = $k; | |||
} | |||
$seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY); | |||
if ($scatterStyle == 'lineMarker') { | |||
$seriesPlot->SetLinkPoints(); | |||
$seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]); | |||
} elseif ($scatterStyle == 'smoothMarker') { | |||
$spline = new Spline($dataValuesY, $dataValuesX); | |||
list($splineDataY, $splineDataX) = $spline->Get(count($dataValuesX) * self::$width / 20); | |||
$lplot = new LinePlot($splineDataX, $splineDataY); | |||
$lplot->SetColor(self::$colourSet[self::$plotColour]); | |||
$this->graph->Add($lplot); | |||
} | |||
if ($bubble) { | |||
$this->formatPointMarker($seriesPlot, 'dot'); | |||
$seriesPlot->mark->SetColor('black'); | |||
$seriesPlot->mark->SetSize($bubbleSize); | |||
} else { | |||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); | |||
$this->formatPointMarker($seriesPlot, $marker); | |||
} | |||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); | |||
$seriesPlot->SetLegend($dataLabel); | |||
$this->graph->Add($seriesPlot); | |||
} | |||
} | |||
private function renderPlotRadar($groupID) | |||
{ | |||
$radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$seriesPlots = array(); | |||
// Loop through each data series in turn | |||
for ($i = 0; $i < $seriesCount; ++$i) { | |||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); | |||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); | |||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); | |||
$dataValues = array(); | |||
foreach ($dataValuesY as $k => $dataValueY) { | |||
$dataValues[$k] = implode(' ', array_reverse($dataValueY)); | |||
} | |||
$tmp = array_shift($dataValues); | |||
$dataValues[] = $tmp; | |||
$tmp = array_shift($dataValuesX); | |||
$dataValuesX[] = $tmp; | |||
$this->graph->SetTitles(array_reverse($dataValues)); | |||
$seriesPlot = new RadarPlot(array_reverse($dataValuesX)); | |||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); | |||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); | |||
if ($radarStyle == 'filled') { | |||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour]); | |||
} | |||
$this->formatPointMarker($seriesPlot, $marker); | |||
$seriesPlot->SetLegend($dataLabel); | |||
$this->graph->Add($seriesPlot); | |||
} | |||
} | |||
private function renderPlotContour($groupID) | |||
{ | |||
$contourStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$seriesPlots = array(); | |||
$dataValues = array(); | |||
// Loop through each data series in turn | |||
for ($i = 0; $i < $seriesCount; ++$i) { | |||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); | |||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); | |||
$dataValues[$i] = $dataValuesX; | |||
} | |||
$seriesPlot = new ContourPlot($dataValues); | |||
$this->graph->Add($seriesPlot); | |||
} | |||
private function renderPlotStock($groupID) | |||
{ | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$plotOrder = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder(); | |||
$dataValues = array(); | |||
// Loop through each data series in turn and build the plot arrays | |||
foreach ($plotOrder as $i => $v) { | |||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v)->getDataValues(); | |||
foreach ($dataValuesX as $j => $dataValueX) { | |||
$dataValues[$plotOrder[$i]][$j] = $dataValueX; | |||
} | |||
} | |||
if (empty($dataValues)) { | |||
return; | |||
} | |||
$dataValuesPlot = array(); | |||
// Flatten the plot arrays to a single dimensional array to work with jpgraph | |||
for ($j = 0; $j < count($dataValues[0]); ++$j) { | |||
for ($i = 0; $i < $seriesCount; ++$i) { | |||
$dataValuesPlot[] = $dataValues[$i][$j]; | |||
} | |||
} | |||
// Set the x-axis labels | |||
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); | |||
if ($labelCount > 0) { | |||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); | |||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); | |||
$this->graph->xaxis->SetTickLabels($datasetLabels); | |||
} | |||
$seriesPlot = new StockPlot($dataValuesPlot); | |||
$seriesPlot->SetWidth(20); | |||
$this->graph->Add($seriesPlot); | |||
} | |||
private function renderAreaChart($groupCount, $dimensions = '2d') | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_line.php'); | |||
$this->renderCartesianPlotArea(); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$this->renderPlotLine($i, true, false, $dimensions); | |||
} | |||
} | |||
private function renderLineChart($groupCount, $dimensions = '2d') | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_line.php'); | |||
$this->renderCartesianPlotArea(); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$this->renderPlotLine($i, false, false, $dimensions); | |||
} | |||
} | |||
private function renderBarChart($groupCount, $dimensions = '2d') | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_bar.php'); | |||
$this->renderCartesianPlotArea(); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$this->renderPlotBar($i, $dimensions); | |||
} | |||
} | |||
private function renderScatterChart($groupCount) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_scatter.php'); | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_regstat.php'); | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_line.php'); | |||
$this->renderCartesianPlotArea('linlin'); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$this->renderPlotScatter($i, false); | |||
} | |||
} | |||
private function renderBubbleChart($groupCount) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_scatter.php'); | |||
$this->renderCartesianPlotArea('linlin'); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$this->renderPlotScatter($i, true); | |||
} | |||
} | |||
private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_pie.php'); | |||
if ($dimensions == '3d') { | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_pie3d.php'); | |||
} | |||
$this->renderPiePlotArea($doughnut); | |||
$iLimit = ($multiplePlots) ? $groupCount : 1; | |||
for ($groupID = 0; $groupID < $iLimit; ++$groupID) { | |||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); | |||
$exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | |||
if ($groupID == 0) { | |||
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); | |||
if ($labelCount > 0) { | |||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); | |||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); | |||
} | |||
} | |||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | |||
$seriesPlots = array(); | |||
// For pie charts, we only display the first series: doughnut charts generally display all series | |||
$jLimit = ($multiplePlots) ? $seriesCount : 1; | |||
// Loop through each data series in turn | |||
for ($j = 0; $j < $jLimit; ++$j) { | |||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues(); | |||
// Fill in any missing values in the $dataValues array | |||
$testCurrentIndex = 0; | |||
foreach ($dataValues as $k => $dataValue) { | |||
while ($k != $testCurrentIndex) { | |||
$dataValues[$testCurrentIndex] = null; | |||
++$testCurrentIndex; | |||
} | |||
++$testCurrentIndex; | |||
} | |||
if ($dimensions == '3d') { | |||
$seriesPlot = new PiePlot3D($dataValues); | |||
} else { | |||
if ($doughnut) { | |||
$seriesPlot = new PiePlotC($dataValues); | |||
} else { | |||
$seriesPlot = new PiePlot($dataValues); | |||
} | |||
} | |||
if ($multiplePlots) { | |||
$seriesPlot->SetSize(($jLimit-$j) / ($jLimit * 4)); | |||
} | |||
if ($doughnut) { | |||
$seriesPlot->SetMidColor('white'); | |||
} | |||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); | |||
if (count($datasetLabels) > 0) { | |||
$seriesPlot->SetLabels(array_fill(0, count($datasetLabels), '')); | |||
} | |||
if ($dimensions != '3d') { | |||
$seriesPlot->SetGuideLines(false); | |||
} | |||
if ($j == 0) { | |||
if ($exploded) { | |||
$seriesPlot->ExplodeAll(); | |||
} | |||
$seriesPlot->SetLegends($datasetLabels); | |||
} | |||
$this->graph->Add($seriesPlot); | |||
} | |||
} | |||
} | |||
private function renderRadarChart($groupCount) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_radar.php'); | |||
$this->renderRadarPlotArea(); | |||
for ($groupID = 0; $groupID < $groupCount; ++$groupID) { | |||
$this->renderPlotRadar($groupID); | |||
} | |||
} | |||
private function renderStockChart($groupCount) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_stock.php'); | |||
$this->renderCartesianPlotArea('intint'); | |||
for ($groupID = 0; $groupID < $groupCount; ++$groupID) { | |||
$this->renderPlotStock($groupID); | |||
} | |||
} | |||
private function renderContourChart($groupCount, $dimensions) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_contour.php'); | |||
$this->renderCartesianPlotArea('intint'); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$this->renderPlotContour($i); | |||
} | |||
} | |||
private function renderCombinationChart($groupCount, $dimensions, $outputDestination) | |||
{ | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_line.php'); | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_bar.php'); | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_scatter.php'); | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_regstat.php'); | |||
require_once(PHPExcel_Settings::getChartRendererPath().'jpgraph_line.php'); | |||
$this->renderCartesianPlotArea(); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$dimensions = null; | |||
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); | |||
switch ($chartType) { | |||
case 'area3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'areaChart': | |||
$this->renderPlotLine($i, true, true, $dimensions); | |||
break; | |||
case 'bar3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'barChart': | |||
$this->renderPlotBar($i, $dimensions); | |||
break; | |||
case 'line3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'lineChart': | |||
$this->renderPlotLine($i, false, true, $dimensions); | |||
break; | |||
case 'scatterChart': | |||
$this->renderPlotScatter($i, false); | |||
break; | |||
case 'bubbleChart': | |||
$this->renderPlotScatter($i, true); | |||
break; | |||
default: | |||
$this->graph = null; | |||
return false; | |||
} | |||
} | |||
$this->renderLegend(); | |||
$this->graph->Stroke($outputDestination); | |||
return true; | |||
} | |||
public function render($outputDestination) | |||
{ | |||
self::$plotColour = 0; | |||
$groupCount = $this->chart->getPlotArea()->getPlotGroupCount(); | |||
$dimensions = null; | |||
if ($groupCount == 1) { | |||
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType(); | |||
} else { | |||
$chartTypes = array(); | |||
for ($i = 0; $i < $groupCount; ++$i) { | |||
$chartTypes[] = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); | |||
} | |||
$chartTypes = array_unique($chartTypes); | |||
if (count($chartTypes) == 1) { | |||
$chartType = array_pop($chartTypes); | |||
} elseif (count($chartTypes) == 0) { | |||
echo 'Chart is not yet implemented<br />'; | |||
return false; | |||
} else { | |||
return $this->renderCombinationChart($groupCount, $dimensions, $outputDestination); | |||
} | |||
} | |||
switch ($chartType) { | |||
case 'area3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'areaChart': | |||
$this->renderAreaChart($groupCount, $dimensions); | |||
break; | |||
case 'bar3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'barChart': | |||
$this->renderBarChart($groupCount, $dimensions); | |||
break; | |||
case 'line3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'lineChart': | |||
$this->renderLineChart($groupCount, $dimensions); | |||
break; | |||
case 'pie3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'pieChart': | |||
$this->renderPieChart($groupCount, $dimensions, false, false); | |||
break; | |||
case 'doughnut3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'doughnutChart': | |||
$this->renderPieChart($groupCount, $dimensions, true, true); | |||
break; | |||
case 'scatterChart': | |||
$this->renderScatterChart($groupCount); | |||
break; | |||
case 'bubbleChart': | |||
$this->renderBubbleChart($groupCount); | |||
break; | |||
case 'radarChart': | |||
$this->renderRadarChart($groupCount); | |||
break; | |||
case 'surface3DChart': | |||
$dimensions = '3d'; | |||
// no break | |||
case 'surfaceChart': | |||
$this->renderContourChart($groupCount, $dimensions); | |||
break; | |||
case 'stockChart': | |||
$this->renderStockChart($groupCount, $dimensions); | |||
break; | |||
default: | |||
echo $chartType.' is not yet implemented<br />'; | |||
return false; | |||
} | |||
$this->renderLegend(); | |||
$this->graph->Stroke($outputDestination); | |||
return true; | |||
} | |||
/** | |||
* Create a new PHPExcel_Chart_Renderer_jpgraph | |||
*/ | |||
public function __construct(PHPExcel_Chart $chart) | |||
{ | |||
$this->graph = null; | |||
$this->chart = $chart; | |||
} | |||
} |
@ -0,0 +1,86 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Chart_Title | |||
* | |||
* Copyright (c) 2006 - 2015 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_Chart | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Chart_Title | |||
{ | |||
/** | |||
* Title Caption | |||
* | |||
* @var string | |||
*/ | |||
private $caption = null; | |||
/** | |||
* Title Layout | |||
* | |||
* @var PHPExcel_Chart_Layout | |||
*/ | |||
private $layout = null; | |||
/** | |||
* Create a new PHPExcel_Chart_Title | |||
*/ | |||
public function __construct($caption = null, PHPExcel_Chart_Layout $layout = null) | |||
{ | |||
$this->caption = $caption; | |||
$this->layout = $layout; | |||
} | |||
/** | |||
* Get caption | |||
* | |||
* @return string | |||
*/ | |||
public function getCaption() | |||
{ | |||
return $this->caption; | |||
} | |||
/** | |||
* Set caption | |||
* | |||
* @param string $caption | |||
* @return PHPExcel_Chart_Title | |||
*/ | |||
public function setCaption($caption = null) | |||
{ | |||
$this->caption = $caption; | |||
return $this; | |||
} | |||
/** | |||
* Get Layout | |||
* | |||
* @return PHPExcel_Chart_Layout | |||
*/ | |||
public function getLayout() | |||
{ | |||
return $this->layout; | |||
} | |||
} |
@ -0,0 +1,338 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Comment | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Comment implements PHPExcel_IComparable | |||
{ | |||
/** | |||
* Author | |||
* | |||
* @var string | |||
*/ | |||
private $author; | |||
/** | |||
* Rich text comment | |||
* | |||
* @var PHPExcel_RichText | |||
*/ | |||
private $text; | |||
/** | |||
* Comment width (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @var string | |||
*/ | |||
private $width = '96pt'; | |||
/** | |||
* Left margin (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @var string | |||
*/ | |||
private $marginLeft = '59.25pt'; | |||
/** | |||
* Top margin (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @var string | |||
*/ | |||
private $marginTop = '1.5pt'; | |||
/** | |||
* Visible | |||
* | |||
* @var boolean | |||
*/ | |||
private $visible = false; | |||
/** | |||
* Comment height (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @var string | |||
*/ | |||
private $height = '55.5pt'; | |||
/** | |||
* Comment fill color | |||
* | |||
* @var PHPExcel_Style_Color | |||
*/ | |||
private $fillColor; | |||
/** | |||
* Alignment | |||
* | |||
* @var string | |||
*/ | |||
private $alignment; | |||
/** | |||
* Create a new PHPExcel_Comment | |||
* | |||
* @throws PHPExcel_Exception | |||
*/ | |||
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; | |||
} | |||
/** | |||
* Get Author | |||
* | |||
* @return string | |||
*/ | |||
public function getAuthor() | |||
{ | |||
return $this->author; | |||
} | |||
/** | |||
* Set Author | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setAuthor($pValue = '') | |||
{ | |||
$this->author = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Rich text comment | |||
* | |||
* @return PHPExcel_RichText | |||
*/ | |||
public function getText() | |||
{ | |||
return $this->text; | |||
} | |||
/** | |||
* Set Rich text comment | |||
* | |||
* @param PHPExcel_RichText $pValue | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setText(PHPExcel_RichText $pValue) | |||
{ | |||
$this->text = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get comment width (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @return string | |||
*/ | |||
public function getWidth() | |||
{ | |||
return $this->width; | |||
} | |||
/** | |||
* Set comment width (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setWidth($value = '96pt') | |||
{ | |||
$this->width = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get comment height (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @return string | |||
*/ | |||
public function getHeight() | |||
{ | |||
return $this->height; | |||
} | |||
/** | |||
* Set comment height (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setHeight($value = '55.5pt') | |||
{ | |||
$this->height = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get left margin (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @return string | |||
*/ | |||
public function getMarginLeft() | |||
{ | |||
return $this->marginLeft; | |||
} | |||
/** | |||
* Set left margin (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setMarginLeft($value = '59.25pt') | |||
{ | |||
$this->marginLeft = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get top margin (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @return string | |||
*/ | |||
public function getMarginTop() | |||
{ | |||
return $this->marginTop; | |||
} | |||
/** | |||
* Set top margin (CSS style, i.e. XXpx or YYpt) | |||
* | |||
* @param string $value | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setMarginTop($value = '1.5pt') | |||
{ | |||
$this->marginTop = $value; | |||
return $this; | |||
} | |||
/** | |||
* Is the comment visible by default? | |||
* | |||
* @return boolean | |||
*/ | |||
public function getVisible() | |||
{ | |||
return $this->visible; | |||
} | |||
/** | |||
* Set comment default visibility | |||
* | |||
* @param boolean $value | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setVisible($value = false) | |||
{ | |||
$this->visible = $value; | |||
return $this; | |||
} | |||
/** | |||
* Get fill color | |||
* | |||
* @return PHPExcel_Style_Color | |||
*/ | |||
public function getFillColor() | |||
{ | |||
return $this->fillColor; | |||
} | |||
/** | |||
* Set Alignment | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_Comment | |||
*/ | |||
public function setAlignment($pValue = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL) | |||
{ | |||
$this->alignment = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Alignment | |||
* | |||
* @return string | |||
*/ | |||
public function getAlignment() | |||
{ | |||
return $this->alignment; | |||
} | |||
/** | |||
* Get hash code | |||
* | |||
* @return string Hash code | |||
*/ | |||
public function getHashCode() | |||
{ | |||
return md5( | |||
$this->author . | |||
$this->text->getHashCode() . | |||
$this->width . | |||
$this->height . | |||
$this->marginLeft . | |||
$this->marginTop . | |||
($this->visible ? 1 : 0) . | |||
$this->fillColor->getHashCode() . | |||
$this->alignment . | |||
__CLASS__ | |||
); | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if (is_object($value)) { | |||
$this->$key = clone $value; | |||
} else { | |||
$this->$key = $value; | |||
} | |||
} | |||
} | |||
/** | |||
* Convert to string | |||
* | |||
* @return string | |||
*/ | |||
public function __toString() | |||
{ | |||
return $this->text->getPlainText(); | |||
} | |||
} |
@ -0,0 +1,611 @@ | |||
<?php | |||
/** | |||
* PHPExcel_DocumentProperties | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_DocumentProperties | |||
{ | |||
/** constants */ | |||
const PROPERTY_TYPE_BOOLEAN = 'b'; | |||
const PROPERTY_TYPE_INTEGER = 'i'; | |||
const PROPERTY_TYPE_FLOAT = 'f'; | |||
const PROPERTY_TYPE_DATE = 'd'; | |||
const PROPERTY_TYPE_STRING = 's'; | |||
const PROPERTY_TYPE_UNKNOWN = 'u'; | |||
/** | |||
* Creator | |||
* | |||
* @var string | |||
*/ | |||
private $creator = 'Unknown Creator'; | |||
/** | |||
* LastModifiedBy | |||
* | |||
* @var string | |||
*/ | |||
private $lastModifiedBy; | |||
/** | |||
* Created | |||
* | |||
* @var datetime | |||
*/ | |||
private $created; | |||
/** | |||
* Modified | |||
* | |||
* @var datetime | |||
*/ | |||
private $modified; | |||
/** | |||
* Title | |||
* | |||
* @var string | |||
*/ | |||
private $title = 'Untitled Spreadsheet'; | |||
/** | |||
* Description | |||
* | |||
* @var string | |||
*/ | |||
private $description = ''; | |||
/** | |||
* Subject | |||
* | |||
* @var string | |||
*/ | |||
private $subject = ''; | |||
/** | |||
* Keywords | |||
* | |||
* @var string | |||
*/ | |||
private $keywords = ''; | |||
/** | |||
* Category | |||
* | |||
* @var string | |||
*/ | |||
private $category = ''; | |||
/** | |||
* Manager | |||
* | |||
* @var string | |||
*/ | |||
private $manager = ''; | |||
/** | |||
* Company | |||
* | |||
* @var string | |||
*/ | |||
private $company = 'Microsoft Corporation'; | |||
/** | |||
* Custom Properties | |||
* | |||
* @var string | |||
*/ | |||
private $customProperties = array(); | |||
/** | |||
* Create a new PHPExcel_DocumentProperties | |||
*/ | |||
public function __construct() | |||
{ | |||
// Initialise values | |||
$this->lastModifiedBy = $this->creator; | |||
$this->created = time(); | |||
$this->modified = time(); | |||
} | |||
/** | |||
* Get Creator | |||
* | |||
* @return string | |||
*/ | |||
public function getCreator() | |||
{ | |||
return $this->creator; | |||
} | |||
/** | |||
* Set Creator | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setCreator($pValue = '') | |||
{ | |||
$this->creator = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Last Modified By | |||
* | |||
* @return string | |||
*/ | |||
public function getLastModifiedBy() | |||
{ | |||
return $this->lastModifiedBy; | |||
} | |||
/** | |||
* Set Last Modified By | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setLastModifiedBy($pValue = '') | |||
{ | |||
$this->lastModifiedBy = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Created | |||
* | |||
* @return datetime | |||
*/ | |||
public function getCreated() | |||
{ | |||
return $this->created; | |||
} | |||
/** | |||
* Set Created | |||
* | |||
* @param datetime $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setCreated($pValue = null) | |||
{ | |||
if ($pValue === null) { | |||
$pValue = time(); | |||
} elseif (is_string($pValue)) { | |||
if (is_numeric($pValue)) { | |||
$pValue = intval($pValue); | |||
} else { | |||
$pValue = strtotime($pValue); | |||
} | |||
} | |||
$this->created = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Modified | |||
* | |||
* @return datetime | |||
*/ | |||
public function getModified() | |||
{ | |||
return $this->modified; | |||
} | |||
/** | |||
* Set Modified | |||
* | |||
* @param datetime $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setModified($pValue = null) | |||
{ | |||
if ($pValue === null) { | |||
$pValue = time(); | |||
} elseif (is_string($pValue)) { | |||
if (is_numeric($pValue)) { | |||
$pValue = intval($pValue); | |||
} else { | |||
$pValue = strtotime($pValue); | |||
} | |||
} | |||
$this->modified = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Title | |||
* | |||
* @return string | |||
*/ | |||
public function getTitle() | |||
{ | |||
return $this->title; | |||
} | |||
/** | |||
* Set Title | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setTitle($pValue = '') | |||
{ | |||
$this->title = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Description | |||
* | |||
* @return string | |||
*/ | |||
public function getDescription() | |||
{ | |||
return $this->description; | |||
} | |||
/** | |||
* Set Description | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setDescription($pValue = '') | |||
{ | |||
$this->description = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Subject | |||
* | |||
* @return string | |||
*/ | |||
public function getSubject() | |||
{ | |||
return $this->subject; | |||
} | |||
/** | |||
* Set Subject | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setSubject($pValue = '') | |||
{ | |||
$this->subject = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Keywords | |||
* | |||
* @return string | |||
*/ | |||
public function getKeywords() | |||
{ | |||
return $this->keywords; | |||
} | |||
/** | |||
* Set Keywords | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setKeywords($pValue = '') | |||
{ | |||
$this->keywords = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Category | |||
* | |||
* @return string | |||
*/ | |||
public function getCategory() | |||
{ | |||
return $this->category; | |||
} | |||
/** | |||
* Set Category | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setCategory($pValue = '') | |||
{ | |||
$this->category = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Company | |||
* | |||
* @return string | |||
*/ | |||
public function getCompany() | |||
{ | |||
return $this->company; | |||
} | |||
/** | |||
* Set Company | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setCompany($pValue = '') | |||
{ | |||
$this->company = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get Manager | |||
* | |||
* @return string | |||
*/ | |||
public function getManager() | |||
{ | |||
return $this->manager; | |||
} | |||
/** | |||
* Set Manager | |||
* | |||
* @param string $pValue | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setManager($pValue = '') | |||
{ | |||
$this->manager = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get a List of Custom Property Names | |||
* | |||
* @return array of string | |||
*/ | |||
public function getCustomProperties() | |||
{ | |||
return array_keys($this->customProperties); | |||
} | |||
/** | |||
* Check if a Custom Property is defined | |||
* | |||
* @param string $propertyName | |||
* @return boolean | |||
*/ | |||
public function isCustomPropertySet($propertyName) | |||
{ | |||
return isset($this->customProperties[$propertyName]); | |||
} | |||
/** | |||
* Get a Custom Property Value | |||
* | |||
* @param string $propertyName | |||
* @return string | |||
*/ | |||
public function getCustomPropertyValue($propertyName) | |||
{ | |||
if (isset($this->customProperties[$propertyName])) { | |||
return $this->customProperties[$propertyName]['value']; | |||
} | |||
} | |||
/** | |||
* Get a Custom Property Type | |||
* | |||
* @param string $propertyName | |||
* @return string | |||
*/ | |||
public function getCustomPropertyType($propertyName) | |||
{ | |||
if (isset($this->customProperties[$propertyName])) { | |||
return $this->customProperties[$propertyName]['type']; | |||
} | |||
} | |||
/** | |||
* Set a Custom Property | |||
* | |||
* @param string $propertyName | |||
* @param mixed $propertyValue | |||
* @param string $propertyType | |||
* 'i' : Integer | |||
* 'f' : Floating Point | |||
* 's' : String | |||
* 'd' : Date/Time | |||
* 'b' : Boolean | |||
* @return PHPExcel_DocumentProperties | |||
*/ | |||
public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) | |||
{ | |||
if (($propertyType === null) || (!in_array($propertyType, array(self::PROPERTY_TYPE_INTEGER, | |||
self::PROPERTY_TYPE_FLOAT, | |||
self::PROPERTY_TYPE_STRING, | |||
self::PROPERTY_TYPE_DATE, | |||
self::PROPERTY_TYPE_BOOLEAN)))) { | |||
if ($propertyValue === null) { | |||
$propertyType = self::PROPERTY_TYPE_STRING; | |||
} elseif (is_float($propertyValue)) { | |||
$propertyType = self::PROPERTY_TYPE_FLOAT; | |||
} elseif (is_int($propertyValue)) { | |||
$propertyType = self::PROPERTY_TYPE_INTEGER; | |||
} elseif (is_bool($propertyValue)) { | |||
$propertyType = self::PROPERTY_TYPE_BOOLEAN; | |||
} else { | |||
$propertyType = self::PROPERTY_TYPE_STRING; | |||
} | |||
} | |||
$this->customProperties[$propertyName] = array( | |||
'value' => $propertyValue, | |||
'type' => $propertyType | |||
); | |||
return $this; | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if (is_object($value)) { | |||
$this->$key = clone $value; | |||
} else { | |||
$this->$key = $value; | |||
} | |||
} | |||
} | |||
public static function convertProperty($propertyValue, $propertyType) | |||
{ | |||
switch ($propertyType) { | |||
case 'empty': // Empty | |||
return ''; | |||
break; | |||
case 'null': // Null | |||
return null; | |||
break; | |||
case 'i1': // 1-Byte Signed Integer | |||
case 'i2': // 2-Byte Signed Integer | |||
case 'i4': // 4-Byte Signed Integer | |||
case 'i8': // 8-Byte Signed Integer | |||
case 'int': // Integer | |||
return (int) $propertyValue; | |||
break; | |||
case 'ui1': // 1-Byte Unsigned Integer | |||
case 'ui2': // 2-Byte Unsigned Integer | |||
case 'ui4': // 4-Byte Unsigned Integer | |||
case 'ui8': // 8-Byte Unsigned Integer | |||
case 'uint': // Unsigned Integer | |||
return abs((int) $propertyValue); | |||
break; | |||
case 'r4': // 4-Byte Real Number | |||
case 'r8': // 8-Byte Real Number | |||
case 'decimal': // Decimal | |||
return (float) $propertyValue; | |||
break; | |||
case 'lpstr': // LPSTR | |||
case 'lpwstr': // LPWSTR | |||
case 'bstr': // Basic String | |||
return $propertyValue; | |||
break; | |||
case 'date': // Date and Time | |||
case 'filetime': // File Time | |||
return strtotime($propertyValue); | |||
break; | |||
case 'bool': // Boolean | |||
return ($propertyValue == 'true') ? true : false; | |||
break; | |||
case 'cy': // Currency | |||
case 'error': // Error Status Code | |||
case 'vector': // Vector | |||
case 'array': // Array | |||
case 'blob': // Binary Blob | |||
case 'oblob': // Binary Blob Object | |||
case 'stream': // Binary Stream | |||
case 'ostream': // Binary Stream Object | |||
case 'storage': // Binary Storage | |||
case 'ostorage': // Binary Storage Object | |||
case 'vstream': // Binary Versioned Stream | |||
case 'clsid': // Class ID | |||
case 'cf': // Clipboard Data | |||
return $propertyValue; | |||
break; | |||
} | |||
return $propertyValue; | |||
} | |||
public static function convertPropertyType($propertyType) | |||
{ | |||
switch ($propertyType) { | |||
case 'i1': // 1-Byte Signed Integer | |||
case 'i2': // 2-Byte Signed Integer | |||
case 'i4': // 4-Byte Signed Integer | |||
case 'i8': // 8-Byte Signed Integer | |||
case 'int': // Integer | |||
case 'ui1': // 1-Byte Unsigned Integer | |||
case 'ui2': // 2-Byte Unsigned Integer | |||
case 'ui4': // 4-Byte Unsigned Integer | |||
case 'ui8': // 8-Byte Unsigned Integer | |||
case 'uint': // Unsigned Integer | |||
return self::PROPERTY_TYPE_INTEGER; | |||
break; | |||
case 'r4': // 4-Byte Real Number | |||
case 'r8': // 8-Byte Real Number | |||
case 'decimal': // Decimal | |||
return self::PROPERTY_TYPE_FLOAT; | |||
break; | |||
case 'empty': // Empty | |||
case 'null': // Null | |||
case 'lpstr': // LPSTR | |||
case 'lpwstr': // LPWSTR | |||
case 'bstr': // Basic String | |||
return self::PROPERTY_TYPE_STRING; | |||
break; | |||
case 'date': // Date and Time | |||
case 'filetime': // File Time | |||
return self::PROPERTY_TYPE_DATE; | |||
break; | |||
case 'bool': // Boolean | |||
return self::PROPERTY_TYPE_BOOLEAN; | |||
break; | |||
case 'cy': // Currency | |||
case 'error': // Error Status Code | |||
case 'vector': // Vector | |||
case 'array': // Array | |||
case 'blob': // Binary Blob | |||
case 'oblob': // Binary Blob Object | |||
case 'stream': // Binary Stream | |||
case 'ostream': // Binary Stream Object | |||
case 'storage': // Binary Storage | |||
case 'ostorage': // Binary Storage Object | |||
case 'vstream': // Binary Versioned Stream | |||
case 'clsid': // Class ID | |||
case 'cf': // Clipboard Data | |||
return self::PROPERTY_TYPE_UNKNOWN; | |||
break; | |||
} | |||
return self::PROPERTY_TYPE_UNKNOWN; | |||
} | |||
} |
@ -0,0 +1,222 @@ | |||
<?php | |||
/** | |||
* PHPExcel_DocumentSecurity | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_DocumentSecurity | |||
{ | |||
/** | |||
* LockRevision | |||
* | |||
* @var boolean | |||
*/ | |||
private $lockRevision; | |||
/** | |||
* LockStructure | |||
* | |||
* @var boolean | |||
*/ | |||
private $lockStructure; | |||
/** | |||
* LockWindows | |||
* | |||
* @var boolean | |||
*/ | |||
private $lockWindows; | |||
/** | |||
* RevisionsPassword | |||
* | |||
* @var string | |||
*/ | |||
private $revisionsPassword; | |||
/** | |||
* WorkbookPassword | |||
* | |||
* @var string | |||
*/ | |||
private $workbookPassword; | |||
/** | |||
* Create a new PHPExcel_DocumentSecurity | |||
*/ | |||
public function __construct() | |||
{ | |||
// Initialise values | |||
$this->lockRevision = false; | |||
$this->lockStructure = false; | |||
$this->lockWindows = false; | |||
$this->revisionsPassword = ''; | |||
$this->workbookPassword = ''; | |||
} | |||
/** | |||
* Is some sort of document security enabled? | |||
* | |||
* @return boolean | |||
*/ | |||
public function isSecurityEnabled() | |||
{ | |||
return $this->lockRevision || | |||
$this->lockStructure || | |||
$this->lockWindows; | |||
} | |||
/** | |||
* Get LockRevision | |||
* | |||
* @return boolean | |||
*/ | |||
public function getLockRevision() | |||
{ | |||
return $this->lockRevision; | |||
} | |||
/** | |||
* Set LockRevision | |||
* | |||
* @param boolean $pValue | |||
* @return PHPExcel_DocumentSecurity | |||
*/ | |||
public function setLockRevision($pValue = false) | |||
{ | |||
$this->lockRevision = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get LockStructure | |||
* | |||
* @return boolean | |||
*/ | |||
public function getLockStructure() | |||
{ | |||
return $this->lockStructure; | |||
} | |||
/** | |||
* Set LockStructure | |||
* | |||
* @param boolean $pValue | |||
* @return PHPExcel_DocumentSecurity | |||
*/ | |||
public function setLockStructure($pValue = false) | |||
{ | |||
$this->lockStructure = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get LockWindows | |||
* | |||
* @return boolean | |||
*/ | |||
public function getLockWindows() | |||
{ | |||
return $this->lockWindows; | |||
} | |||
/** | |||
* Set LockWindows | |||
* | |||
* @param boolean $pValue | |||
* @return PHPExcel_DocumentSecurity | |||
*/ | |||
public function setLockWindows($pValue = false) | |||
{ | |||
$this->lockWindows = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get RevisionsPassword (hashed) | |||
* | |||
* @return string | |||
*/ | |||
public function getRevisionsPassword() | |||
{ | |||
return $this->revisionsPassword; | |||
} | |||
/** | |||
* Set RevisionsPassword | |||
* | |||
* @param string $pValue | |||
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true | |||
* @return PHPExcel_DocumentSecurity | |||
*/ | |||
public function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) | |||
{ | |||
if (!$pAlreadyHashed) { | |||
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); | |||
} | |||
$this->revisionsPassword = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get WorkbookPassword (hashed) | |||
* | |||
* @return string | |||
*/ | |||
public function getWorkbookPassword() | |||
{ | |||
return $this->workbookPassword; | |||
} | |||
/** | |||
* Set WorkbookPassword | |||
* | |||
* @param string $pValue | |||
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true | |||
* @return PHPExcel_DocumentSecurity | |||
*/ | |||
public function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) | |||
{ | |||
if (!$pAlreadyHashed) { | |||
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); | |||
} | |||
$this->workbookPassword = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if (is_object($value)) { | |||
$this->$key = clone $value; | |||
} else { | |||
$this->$key = $value; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,54 @@ | |||
<?php | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
/** | |||
* PHPExcel_Exception | |||
* | |||
* @category PHPExcel | |||
* @package PHPExcel | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
*/ | |||
class PHPExcel_Exception extends Exception | |||
{ | |||
/** | |||
* Error handler callback | |||
* | |||
* @param mixed $code | |||
* @param mixed $string | |||
* @param mixed $file | |||
* @param mixed $line | |||
* @param mixed $context | |||
*/ | |||
public static function errorHandlerCallback($code, $string, $file, $line, $context) | |||
{ | |||
$e = new self($string, $code); | |||
$e->line = $line; | |||
$e->file = $file; | |||
throw $e; | |||
} | |||
} |
@ -0,0 +1,204 @@ | |||
<?php | |||
/** | |||
* PHPExcel_HashTable | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_HashTable | |||
{ | |||
/** | |||
* HashTable elements | |||
* | |||
* @var array | |||
*/ | |||
protected $items = array(); | |||
/** | |||
* HashTable key map | |||
* | |||
* @var array | |||
*/ | |||
protected $keyMap = array(); | |||
/** | |||
* Create a new PHPExcel_HashTable | |||
* | |||
* @param PHPExcel_IComparable[] $pSource Optional source array to create HashTable from | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function __construct($pSource = null) | |||
{ | |||
if ($pSource !== null) { | |||
// Create HashTable | |||
$this->addFromSource($pSource); | |||
} | |||
} | |||
/** | |||
* Add HashTable items from source | |||
* | |||
* @param PHPExcel_IComparable[] $pSource Source array to create HashTable from | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function addFromSource($pSource = null) | |||
{ | |||
// Check if an array was passed | |||
if ($pSource == null) { | |||
return; | |||
} elseif (!is_array($pSource)) { | |||
throw new PHPExcel_Exception('Invalid array parameter passed.'); | |||
} | |||
foreach ($pSource as $item) { | |||
$this->add($item); | |||
} | |||
} | |||
/** | |||
* Add HashTable item | |||
* | |||
* @param PHPExcel_IComparable $pSource Item to add | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function add(PHPExcel_IComparable $pSource = null) | |||
{ | |||
$hash = $pSource->getHashCode(); | |||
if (!isset($this->items[$hash])) { | |||
$this->items[$hash] = $pSource; | |||
$this->keyMap[count($this->items) - 1] = $hash; | |||
} | |||
} | |||
/** | |||
* Remove HashTable item | |||
* | |||
* @param PHPExcel_IComparable $pSource Item to remove | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function remove(PHPExcel_IComparable $pSource = null) | |||
{ | |||
$hash = $pSource->getHashCode(); | |||
if (isset($this->items[$hash])) { | |||
unset($this->items[$hash]); | |||
$deleteKey = -1; | |||
foreach ($this->keyMap as $key => $value) { | |||
if ($deleteKey >= 0) { | |||
$this->keyMap[$key - 1] = $value; | |||
} | |||
if ($value == $hash) { | |||
$deleteKey = $key; | |||
} | |||
} | |||
unset($this->keyMap[count($this->keyMap) - 1]); | |||
} | |||
} | |||
/** | |||
* Clear HashTable | |||
* | |||
*/ | |||
public function clear() | |||
{ | |||
$this->items = array(); | |||
$this->keyMap = array(); | |||
} | |||
/** | |||
* Count | |||
* | |||
* @return int | |||
*/ | |||
public function count() | |||
{ | |||
return count($this->items); | |||
} | |||
/** | |||
* Get index for hash code | |||
* | |||
* @param string $pHashCode | |||
* @return int Index | |||
*/ | |||
public function getIndexForHashCode($pHashCode = '') | |||
{ | |||
return array_search($pHashCode, $this->keyMap); | |||
} | |||
/** | |||
* Get by index | |||
* | |||
* @param int $pIndex | |||
* @return PHPExcel_IComparable | |||
* | |||
*/ | |||
public function getByIndex($pIndex = 0) | |||
{ | |||
if (isset($this->keyMap[$pIndex])) { | |||
return $this->getByHashCode($this->keyMap[$pIndex]); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Get by hashcode | |||
* | |||
* @param string $pHashCode | |||
* @return PHPExcel_IComparable | |||
* | |||
*/ | |||
public function getByHashCode($pHashCode = '') | |||
{ | |||
if (isset($this->items[$pHashCode])) { | |||
return $this->items[$pHashCode]; | |||
} | |||
return null; | |||
} | |||
/** | |||
* HashTable to array | |||
* | |||
* @return PHPExcel_IComparable[] | |||
*/ | |||
public function toArray() | |||
{ | |||
return $this->items; | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if (is_object($value)) { | |||
$this->$key = clone $value; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,808 @@ | |||
<?php | |||
class PHPExcel_Helper_HTML | |||
{ | |||
protected static $colourMap = array( | |||
'aliceblue' => 'f0f8ff', | |||
'antiquewhite' => 'faebd7', | |||
'antiquewhite1' => 'ffefdb', | |||
'antiquewhite2' => 'eedfcc', | |||
'antiquewhite3' => 'cdc0b0', | |||
'antiquewhite4' => '8b8378', | |||
'aqua' => '00ffff', | |||
'aquamarine1' => '7fffd4', | |||
'aquamarine2' => '76eec6', | |||
'aquamarine4' => '458b74', | |||
'azure1' => 'f0ffff', | |||
'azure2' => 'e0eeee', | |||
'azure3' => 'c1cdcd', | |||
'azure4' => '838b8b', | |||
'beige' => 'f5f5dc', | |||
'bisque1' => 'ffe4c4', | |||
'bisque2' => 'eed5b7', | |||
'bisque3' => 'cdb79e', | |||
'bisque4' => '8b7d6b', | |||
'black' => '000000', | |||
'blanchedalmond' => 'ffebcd', | |||
'blue' => '0000ff', | |||
'blue1' => '0000ff', | |||
'blue2' => '0000ee', | |||
'blue4' => '00008b', | |||
'blueviolet' => '8a2be2', | |||
'brown' => 'a52a2a', | |||
'brown1' => 'ff4040', | |||
'brown2' => 'ee3b3b', | |||
'brown3' => 'cd3333', | |||
'brown4' => '8b2323', | |||
'burlywood' => 'deb887', | |||
'burlywood1' => 'ffd39b', | |||
'burlywood2' => 'eec591', | |||
'burlywood3' => 'cdaa7d', | |||
'burlywood4' => '8b7355', | |||
'cadetblue' => '5f9ea0', | |||
'cadetblue1' => '98f5ff', | |||
'cadetblue2' => '8ee5ee', | |||
'cadetblue3' => '7ac5cd', | |||
'cadetblue4' => '53868b', | |||
'chartreuse1' => '7fff00', | |||
'chartreuse2' => '76ee00', | |||
'chartreuse3' => '66cd00', | |||
'chartreuse4' => '458b00', | |||
'chocolate' => 'd2691e', | |||
'chocolate1' => 'ff7f24', | |||
'chocolate2' => 'ee7621', | |||
'chocolate3' => 'cd661d', | |||
'coral' => 'ff7f50', | |||
'coral1' => 'ff7256', | |||
'coral2' => 'ee6a50', | |||
'coral3' => 'cd5b45', | |||
'coral4' => '8b3e2f', | |||
'cornflowerblue' => '6495ed', | |||
'cornsilk1' => 'fff8dc', | |||
'cornsilk2' => 'eee8cd', | |||
'cornsilk3' => 'cdc8b1', | |||
'cornsilk4' => '8b8878', | |||
'cyan1' => '00ffff', | |||
'cyan2' => '00eeee', | |||
'cyan3' => '00cdcd', | |||
'cyan4' => '008b8b', | |||
'darkgoldenrod' => 'b8860b', | |||
'darkgoldenrod1' => 'ffb90f', | |||
'darkgoldenrod2' => 'eead0e', | |||
'darkgoldenrod3' => 'cd950c', | |||
'darkgoldenrod4' => '8b6508', | |||
'darkgreen' => '006400', | |||
'darkkhaki' => 'bdb76b', | |||
'darkolivegreen' => '556b2f', | |||
'darkolivegreen1' => 'caff70', | |||
'darkolivegreen2' => 'bcee68', | |||
'darkolivegreen3' => 'a2cd5a', | |||
'darkolivegreen4' => '6e8b3d', | |||
'darkorange' => 'ff8c00', | |||
'darkorange1' => 'ff7f00', | |||
'darkorange2' => 'ee7600', | |||
'darkorange3' => 'cd6600', | |||
'darkorange4' => '8b4500', | |||
'darkorchid' => '9932cc', | |||
'darkorchid1' => 'bf3eff', | |||
'darkorchid2' => 'b23aee', | |||
'darkorchid3' => '9a32cd', | |||
'darkorchid4' => '68228b', | |||
'darksalmon' => 'e9967a', | |||
'darkseagreen' => '8fbc8f', | |||
'darkseagreen1' => 'c1ffc1', | |||
'darkseagreen2' => 'b4eeb4', | |||
'darkseagreen3' => '9bcd9b', | |||
'darkseagreen4' => '698b69', | |||
'darkslateblue' => '483d8b', | |||
'darkslategray' => '2f4f4f', | |||
'darkslategray1' => '97ffff', | |||
'darkslategray2' => '8deeee', | |||
'darkslategray3' => '79cdcd', | |||
'darkslategray4' => '528b8b', | |||
'darkturquoise' => '00ced1', | |||
'darkviolet' => '9400d3', | |||
'deeppink1' => 'ff1493', | |||
'deeppink2' => 'ee1289', | |||
'deeppink3' => 'cd1076', | |||
'deeppink4' => '8b0a50', | |||
'deepskyblue1' => '00bfff', | |||
'deepskyblue2' => '00b2ee', | |||
'deepskyblue3' => '009acd', | |||
'deepskyblue4' => '00688b', | |||
'dimgray' => '696969', | |||
'dodgerblue1' => '1e90ff', | |||
'dodgerblue2' => '1c86ee', | |||
'dodgerblue3' => '1874cd', | |||
'dodgerblue4' => '104e8b', | |||
'firebrick' => 'b22222', | |||
'firebrick1' => 'ff3030', | |||
'firebrick2' => 'ee2c2c', | |||
'firebrick3' => 'cd2626', | |||
'firebrick4' => '8b1a1a', | |||
'floralwhite' => 'fffaf0', | |||
'forestgreen' => '228b22', | |||
'fuchsia' => 'ff00ff', | |||
'gainsboro' => 'dcdcdc', | |||
'ghostwhite' => 'f8f8ff', | |||
'gold1' => 'ffd700', | |||
'gold2' => 'eec900', | |||
'gold3' => 'cdad00', | |||
'gold4' => '8b7500', | |||
'goldenrod' => 'daa520', | |||
'goldenrod1' => 'ffc125', | |||
'goldenrod2' => 'eeb422', | |||
'goldenrod3' => 'cd9b1d', | |||
'goldenrod4' => '8b6914', | |||
'gray' => 'bebebe', | |||
'gray1' => '030303', | |||
'gray10' => '1a1a1a', | |||
'gray11' => '1c1c1c', | |||
'gray12' => '1f1f1f', | |||
'gray13' => '212121', | |||
'gray14' => '242424', | |||
'gray15' => '262626', | |||
'gray16' => '292929', | |||
'gray17' => '2b2b2b', | |||
'gray18' => '2e2e2e', | |||
'gray19' => '303030', | |||
'gray2' => '050505', | |||
'gray20' => '333333', | |||
'gray21' => '363636', | |||
'gray22' => '383838', | |||
'gray23' => '3b3b3b', | |||
'gray24' => '3d3d3d', | |||
'gray25' => '404040', | |||
'gray26' => '424242', | |||
'gray27' => '454545', | |||
'gray28' => '474747', | |||
'gray29' => '4a4a4a', | |||
'gray3' => '080808', | |||
'gray30' => '4d4d4d', | |||
'gray31' => '4f4f4f', | |||
'gray32' => '525252', | |||
'gray33' => '545454', | |||
'gray34' => '575757', | |||
'gray35' => '595959', | |||
'gray36' => '5c5c5c', | |||
'gray37' => '5e5e5e', | |||
'gray38' => '616161', | |||
'gray39' => '636363', | |||
'gray4' => '0a0a0a', | |||
'gray40' => '666666', | |||
'gray41' => '696969', | |||
'gray42' => '6b6b6b', | |||
'gray43' => '6e6e6e', | |||
'gray44' => '707070', | |||
'gray45' => '737373', | |||
'gray46' => '757575', | |||
'gray47' => '787878', | |||
'gray48' => '7a7a7a', | |||
'gray49' => '7d7d7d', | |||
'gray5' => '0d0d0d', | |||
'gray50' => '7f7f7f', | |||
'gray51' => '828282', | |||
'gray52' => '858585', | |||
'gray53' => '878787', | |||
'gray54' => '8a8a8a', | |||
'gray55' => '8c8c8c', | |||
'gray56' => '8f8f8f', | |||
'gray57' => '919191', | |||
'gray58' => '949494', | |||
'gray59' => '969696', | |||
'gray6' => '0f0f0f', | |||
'gray60' => '999999', | |||
'gray61' => '9c9c9c', | |||
'gray62' => '9e9e9e', | |||
'gray63' => 'a1a1a1', | |||
'gray64' => 'a3a3a3', | |||
'gray65' => 'a6a6a6', | |||
'gray66' => 'a8a8a8', | |||
'gray67' => 'ababab', | |||
'gray68' => 'adadad', | |||
'gray69' => 'b0b0b0', | |||
'gray7' => '121212', | |||
'gray70' => 'b3b3b3', | |||
'gray71' => 'b5b5b5', | |||
'gray72' => 'b8b8b8', | |||
'gray73' => 'bababa', | |||
'gray74' => 'bdbdbd', | |||
'gray75' => 'bfbfbf', | |||
'gray76' => 'c2c2c2', | |||
'gray77' => 'c4c4c4', | |||
'gray78' => 'c7c7c7', | |||
'gray79' => 'c9c9c9', | |||
'gray8' => '141414', | |||
'gray80' => 'cccccc', | |||
'gray81' => 'cfcfcf', | |||
'gray82' => 'd1d1d1', | |||
'gray83' => 'd4d4d4', | |||
'gray84' => 'd6d6d6', | |||
'gray85' => 'd9d9d9', | |||
'gray86' => 'dbdbdb', | |||
'gray87' => 'dedede', | |||
'gray88' => 'e0e0e0', | |||
'gray89' => 'e3e3e3', | |||
'gray9' => '171717', | |||
'gray90' => 'e5e5e5', | |||
'gray91' => 'e8e8e8', | |||
'gray92' => 'ebebeb', | |||
'gray93' => 'ededed', | |||
'gray94' => 'f0f0f0', | |||
'gray95' => 'f2f2f2', | |||
'gray97' => 'f7f7f7', | |||
'gray98' => 'fafafa', | |||
'gray99' => 'fcfcfc', | |||
'green' => '00ff00', | |||
'green1' => '00ff00', | |||
'green2' => '00ee00', | |||
'green3' => '00cd00', | |||
'green4' => '008b00', | |||
'greenyellow' => 'adff2f', | |||
'honeydew1' => 'f0fff0', | |||
'honeydew2' => 'e0eee0', | |||
'honeydew3' => 'c1cdc1', | |||
'honeydew4' => '838b83', | |||
'hotpink' => 'ff69b4', | |||
'hotpink1' => 'ff6eb4', | |||
'hotpink2' => 'ee6aa7', | |||
'hotpink3' => 'cd6090', | |||
'hotpink4' => '8b3a62', | |||
'indianred' => 'cd5c5c', | |||
'indianred1' => 'ff6a6a', | |||
'indianred2' => 'ee6363', | |||
'indianred3' => 'cd5555', | |||
'indianred4' => '8b3a3a', | |||
'ivory1' => 'fffff0', | |||
'ivory2' => 'eeeee0', | |||
'ivory3' => 'cdcdc1', | |||
'ivory4' => '8b8b83', | |||
'khaki' => 'f0e68c', | |||
'khaki1' => 'fff68f', | |||
'khaki2' => 'eee685', | |||
'khaki3' => 'cdc673', | |||
'khaki4' => '8b864e', | |||
'lavender' => 'e6e6fa', | |||
'lavenderblush1' => 'fff0f5', | |||
'lavenderblush2' => 'eee0e5', | |||
'lavenderblush3' => 'cdc1c5', | |||
'lavenderblush4' => '8b8386', | |||
'lawngreen' => '7cfc00', | |||
'lemonchiffon1' => 'fffacd', | |||
'lemonchiffon2' => 'eee9bf', | |||
'lemonchiffon3' => 'cdc9a5', | |||
'lemonchiffon4' => '8b8970', | |||
'light' => 'eedd82', | |||
'lightblue' => 'add8e6', | |||
'lightblue1' => 'bfefff', | |||
'lightblue2' => 'b2dfee', | |||
'lightblue3' => '9ac0cd', | |||
'lightblue4' => '68838b', | |||
'lightcoral' => 'f08080', | |||
'lightcyan1' => 'e0ffff', | |||
'lightcyan2' => 'd1eeee', | |||
'lightcyan3' => 'b4cdcd', | |||
'lightcyan4' => '7a8b8b', | |||
'lightgoldenrod1' => 'ffec8b', | |||
'lightgoldenrod2' => 'eedc82', | |||
'lightgoldenrod3' => 'cdbe70', | |||
'lightgoldenrod4' => '8b814c', | |||
'lightgoldenrodyellow' => 'fafad2', | |||
'lightgray' => 'd3d3d3', | |||
'lightpink' => 'ffb6c1', | |||
'lightpink1' => 'ffaeb9', | |||
'lightpink2' => 'eea2ad', | |||
'lightpink3' => 'cd8c95', | |||
'lightpink4' => '8b5f65', | |||
'lightsalmon1' => 'ffa07a', | |||
'lightsalmon2' => 'ee9572', | |||
'lightsalmon3' => 'cd8162', | |||
'lightsalmon4' => '8b5742', | |||
'lightseagreen' => '20b2aa', | |||
'lightskyblue' => '87cefa', | |||
'lightskyblue1' => 'b0e2ff', | |||
'lightskyblue2' => 'a4d3ee', | |||
'lightskyblue3' => '8db6cd', | |||
'lightskyblue4' => '607b8b', | |||
'lightslateblue' => '8470ff', | |||
'lightslategray' => '778899', | |||
'lightsteelblue' => 'b0c4de', | |||
'lightsteelblue1' => 'cae1ff', | |||
'lightsteelblue2' => 'bcd2ee', | |||
'lightsteelblue3' => 'a2b5cd', | |||
'lightsteelblue4' => '6e7b8b', | |||
'lightyellow1' => 'ffffe0', | |||
'lightyellow2' => 'eeeed1', | |||
'lightyellow3' => 'cdcdb4', | |||
'lightyellow4' => '8b8b7a', | |||
'lime' => '00ff00', | |||
'limegreen' => '32cd32', | |||
'linen' => 'faf0e6', | |||
'magenta' => 'ff00ff', | |||
'magenta2' => 'ee00ee', | |||
'magenta3' => 'cd00cd', | |||
'magenta4' => '8b008b', | |||
'maroon' => 'b03060', | |||
'maroon1' => 'ff34b3', | |||
'maroon2' => 'ee30a7', | |||
'maroon3' => 'cd2990', | |||
'maroon4' => '8b1c62', | |||
'medium' => '66cdaa', | |||
'mediumaquamarine' => '66cdaa', | |||
'mediumblue' => '0000cd', | |||
'mediumorchid' => 'ba55d3', | |||
'mediumorchid1' => 'e066ff', | |||
'mediumorchid2' => 'd15fee', | |||
'mediumorchid3' => 'b452cd', | |||
'mediumorchid4' => '7a378b', | |||
'mediumpurple' => '9370db', | |||
'mediumpurple1' => 'ab82ff', | |||
'mediumpurple2' => '9f79ee', | |||
'mediumpurple3' => '8968cd', | |||
'mediumpurple4' => '5d478b', | |||
'mediumseagreen' => '3cb371', | |||
'mediumslateblue' => '7b68ee', | |||
'mediumspringgreen' => '00fa9a', | |||
'mediumturquoise' => '48d1cc', | |||
'mediumvioletred' => 'c71585', | |||
'midnightblue' => '191970', | |||
'mintcream' => 'f5fffa', | |||
'mistyrose1' => 'ffe4e1', | |||
'mistyrose2' => 'eed5d2', | |||
'mistyrose3' => 'cdb7b5', | |||
'mistyrose4' => '8b7d7b', | |||
'moccasin' => 'ffe4b5', | |||
'navajowhite1' => 'ffdead', | |||
'navajowhite2' => 'eecfa1', | |||
'navajowhite3' => 'cdb38b', | |||
'navajowhite4' => '8b795e', | |||
'navy' => '000080', | |||
'navyblue' => '000080', | |||
'oldlace' => 'fdf5e6', | |||
'olive' => '808000', | |||
'olivedrab' => '6b8e23', | |||
'olivedrab1' => 'c0ff3e', | |||
'olivedrab2' => 'b3ee3a', | |||
'olivedrab4' => '698b22', | |||
'orange' => 'ffa500', | |||
'orange1' => 'ffa500', | |||
'orange2' => 'ee9a00', | |||
'orange3' => 'cd8500', | |||
'orange4' => '8b5a00', | |||
'orangered1' => 'ff4500', | |||
'orangered2' => 'ee4000', | |||
'orangered3' => 'cd3700', | |||
'orangered4' => '8b2500', | |||
'orchid' => 'da70d6', | |||
'orchid1' => 'ff83fa', | |||
'orchid2' => 'ee7ae9', | |||
'orchid3' => 'cd69c9', | |||
'orchid4' => '8b4789', | |||
'pale' => 'db7093', | |||
'palegoldenrod' => 'eee8aa', | |||
'palegreen' => '98fb98', | |||
'palegreen1' => '9aff9a', | |||
'palegreen2' => '90ee90', | |||
'palegreen3' => '7ccd7c', | |||
'palegreen4' => '548b54', | |||
'paleturquoise' => 'afeeee', | |||
'paleturquoise1' => 'bbffff', | |||
'paleturquoise2' => 'aeeeee', | |||
'paleturquoise3' => '96cdcd', | |||
'paleturquoise4' => '668b8b', | |||
'palevioletred' => 'db7093', | |||
'palevioletred1' => 'ff82ab', | |||
'palevioletred2' => 'ee799f', | |||
'palevioletred3' => 'cd6889', | |||
'palevioletred4' => '8b475d', | |||
'papayawhip' => 'ffefd5', | |||
'peachpuff1' => 'ffdab9', | |||
'peachpuff2' => 'eecbad', | |||
'peachpuff3' => 'cdaf95', | |||
'peachpuff4' => '8b7765', | |||
'pink' => 'ffc0cb', | |||
'pink1' => 'ffb5c5', | |||
'pink2' => 'eea9b8', | |||
'pink3' => 'cd919e', | |||
'pink4' => '8b636c', | |||
'plum' => 'dda0dd', | |||
'plum1' => 'ffbbff', | |||
'plum2' => 'eeaeee', | |||
'plum3' => 'cd96cd', | |||
'plum4' => '8b668b', | |||
'powderblue' => 'b0e0e6', | |||
'purple' => 'a020f0', | |||
'rebeccapurple' => '663399', | |||
'purple1' => '9b30ff', | |||
'purple2' => '912cee', | |||
'purple3' => '7d26cd', | |||
'purple4' => '551a8b', | |||
'red' => 'ff0000', | |||
'red1' => 'ff0000', | |||
'red2' => 'ee0000', | |||
'red3' => 'cd0000', | |||
'red4' => '8b0000', | |||
'rosybrown' => 'bc8f8f', | |||
'rosybrown1' => 'ffc1c1', | |||
'rosybrown2' => 'eeb4b4', | |||
'rosybrown3' => 'cd9b9b', | |||
'rosybrown4' => '8b6969', | |||
'royalblue' => '4169e1', | |||
'royalblue1' => '4876ff', | |||
'royalblue2' => '436eee', | |||
'royalblue3' => '3a5fcd', | |||
'royalblue4' => '27408b', | |||
'saddlebrown' => '8b4513', | |||
'salmon' => 'fa8072', | |||
'salmon1' => 'ff8c69', | |||
'salmon2' => 'ee8262', | |||
'salmon3' => 'cd7054', | |||
'salmon4' => '8b4c39', | |||
'sandybrown' => 'f4a460', | |||
'seagreen1' => '54ff9f', | |||
'seagreen2' => '4eee94', | |||
'seagreen3' => '43cd80', | |||
'seagreen4' => '2e8b57', | |||
'seashell1' => 'fff5ee', | |||
'seashell2' => 'eee5de', | |||
'seashell3' => 'cdc5bf', | |||
'seashell4' => '8b8682', | |||
'sienna' => 'a0522d', | |||
'sienna1' => 'ff8247', | |||
'sienna2' => 'ee7942', | |||
'sienna3' => 'cd6839', | |||
'sienna4' => '8b4726', | |||
'silver' => 'c0c0c0', | |||
'skyblue' => '87ceeb', | |||
'skyblue1' => '87ceff', | |||
'skyblue2' => '7ec0ee', | |||
'skyblue3' => '6ca6cd', | |||
'skyblue4' => '4a708b', | |||
'slateblue' => '6a5acd', | |||
'slateblue1' => '836fff', | |||
'slateblue2' => '7a67ee', | |||
'slateblue3' => '6959cd', | |||
'slateblue4' => '473c8b', | |||
'slategray' => '708090', | |||
'slategray1' => 'c6e2ff', | |||
'slategray2' => 'b9d3ee', | |||
'slategray3' => '9fb6cd', | |||
'slategray4' => '6c7b8b', | |||
'snow1' => 'fffafa', | |||
'snow2' => 'eee9e9', | |||
'snow3' => 'cdc9c9', | |||
'snow4' => '8b8989', | |||
'springgreen1' => '00ff7f', | |||
'springgreen2' => '00ee76', | |||
'springgreen3' => '00cd66', | |||
'springgreen4' => '008b45', | |||
'steelblue' => '4682b4', | |||
'steelblue1' => '63b8ff', | |||
'steelblue2' => '5cacee', | |||
'steelblue3' => '4f94cd', | |||
'steelblue4' => '36648b', | |||
'tan' => 'd2b48c', | |||
'tan1' => 'ffa54f', | |||
'tan2' => 'ee9a49', | |||
'tan3' => 'cd853f', | |||
'tan4' => '8b5a2b', | |||
'teal' => '008080', | |||
'thistle' => 'd8bfd8', | |||
'thistle1' => 'ffe1ff', | |||
'thistle2' => 'eed2ee', | |||
'thistle3' => 'cdb5cd', | |||
'thistle4' => '8b7b8b', | |||
'tomato1' => 'ff6347', | |||
'tomato2' => 'ee5c42', | |||
'tomato3' => 'cd4f39', | |||
'tomato4' => '8b3626', | |||
'turquoise' => '40e0d0', | |||
'turquoise1' => '00f5ff', | |||
'turquoise2' => '00e5ee', | |||
'turquoise3' => '00c5cd', | |||
'turquoise4' => '00868b', | |||
'violet' => 'ee82ee', | |||
'violetred' => 'd02090', | |||
'violetred1' => 'ff3e96', | |||
'violetred2' => 'ee3a8c', | |||
'violetred3' => 'cd3278', | |||
'violetred4' => '8b2252', | |||
'wheat' => 'f5deb3', | |||
'wheat1' => 'ffe7ba', | |||
'wheat2' => 'eed8ae', | |||
'wheat3' => 'cdba96', | |||
'wheat4' => '8b7e66', | |||
'white' => 'ffffff', | |||
'whitesmoke' => 'f5f5f5', | |||
'yellow' => 'ffff00', | |||
'yellow1' => 'ffff00', | |||
'yellow2' => 'eeee00', | |||
'yellow3' => 'cdcd00', | |||
'yellow4' => '8b8b00', | |||
'yellowgreen' => '9acd32', | |||
); | |||
protected $face; | |||
protected $size; | |||
protected $color; | |||
protected $bold = false; | |||
protected $italic = false; | |||
protected $underline = false; | |||
protected $superscript = false; | |||
protected $subscript = false; | |||
protected $strikethrough = false; | |||
protected $startTagCallbacks = array( | |||
'font' => 'startFontTag', | |||
'b' => 'startBoldTag', | |||
'strong' => 'startBoldTag', | |||
'i' => 'startItalicTag', | |||
'em' => 'startItalicTag', | |||
'u' => 'startUnderlineTag', | |||
'ins' => 'startUnderlineTag', | |||
'del' => 'startStrikethruTag', | |||
'sup' => 'startSuperscriptTag', | |||
'sub' => 'startSubscriptTag', | |||
); | |||
protected $endTagCallbacks = array( | |||
'font' => 'endFontTag', | |||
'b' => 'endBoldTag', | |||
'strong' => 'endBoldTag', | |||
'i' => 'endItalicTag', | |||
'em' => 'endItalicTag', | |||
'u' => 'endUnderlineTag', | |||
'ins' => 'endUnderlineTag', | |||
'del' => 'endStrikethruTag', | |||
'sup' => 'endSuperscriptTag', | |||
'sub' => 'endSubscriptTag', | |||
'br' => 'breakTag', | |||
'p' => 'breakTag', | |||
'h1' => 'breakTag', | |||
'h2' => 'breakTag', | |||
'h3' => 'breakTag', | |||
'h4' => 'breakTag', | |||
'h5' => 'breakTag', | |||
'h6' => 'breakTag', | |||
); | |||
protected $stack = array(); | |||
protected $stringData = ''; | |||
protected $richTextObject; | |||
protected function initialise() | |||
{ | |||
$this->face = $this->size = $this->color = null; | |||
$this->bold = $this->italic = $this->underline = $this->superscript = $this->subscript = $this->strikethrough = false; | |||
$this->stack = array(); | |||
$this->stringData = ''; | |||
} | |||
public function toRichTextObject($html) | |||
{ | |||
$this->initialise(); | |||
// Create a new DOM object | |||
$dom = new \DOMDocument; | |||
// Load the HTML file into the DOM object | |||
// Note the use of error suppression, because typically this will be an html fragment, so not fully valid markup | |||
$loaded = @$dom->loadHTML($html); | |||
// Discard excess white space | |||
$dom->preserveWhiteSpace = false; | |||
$this->richTextObject = new PHPExcel_RichText();; | |||
$this->parseElements($dom); | |||
// Clean any further spurious whitespace | |||
$this->cleanWhitespace(); | |||
return $this->richTextObject; | |||
} | |||
protected function cleanWhitespace() | |||
{ | |||
foreach ($this->richTextObject->getRichTextElements() as $key => $element) { | |||
$text = $element->getText(); | |||
// Trim any leading spaces on the first run | |||
if ($key == 0) { | |||
$text = ltrim($text); | |||
} | |||
// Trim any spaces immediately after a line break | |||
$text = preg_replace('/\n */mu', "\n", $text); | |||
$element->setText($text); | |||
} | |||
} | |||
protected function buildTextRun() | |||
{ | |||
$text = $this->stringData; | |||
if (trim($text) === '') { | |||
return; | |||
} | |||
$richtextRun = $this->richTextObject->createTextRun($this->stringData); | |||
if ($this->face) { | |||
$richtextRun->getFont()->setName($this->face); | |||
} | |||
if ($this->size) { | |||
$richtextRun->getFont()->setSize($this->size); | |||
} | |||
if ($this->color) { | |||
$richtextRun->getFont()->setColor(new PHPExcel_Style_Color('ff' . $this->color)); | |||
} | |||
if ($this->bold) { | |||
$richtextRun->getFont()->setBold(true); | |||
} | |||
if ($this->italic) { | |||
$richtextRun->getFont()->setItalic(true); | |||
} | |||
if ($this->underline) { | |||
$richtextRun->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); | |||
} | |||
if ($this->superscript) { | |||
$richtextRun->getFont()->setSuperScript(true); | |||
} | |||
if ($this->subscript) { | |||
$richtextRun->getFont()->setSubScript(true); | |||
} | |||
if ($this->strikethrough) { | |||
$richtextRun->getFont()->setStrikethrough(true); | |||
} | |||
$this->stringData = ''; | |||
} | |||
protected function rgbToColour($rgb) | |||
{ | |||
preg_match_all('/\d+/', $rgb, $values); | |||
foreach ($values[0] as &$value) { | |||
$value = str_pad(dechex($value), 2, '0', STR_PAD_LEFT); | |||
} | |||
return implode($values[0]); | |||
} | |||
protected function colourNameLookup($rgb) | |||
{ | |||
return self::$colourMap[$rgb]; | |||
} | |||
protected function startFontTag($tag) | |||
{ | |||
foreach ($tag->attributes as $attribute) { | |||
$attributeName = strtolower($attribute->name); | |||
$attributeValue = $attribute->value; | |||
if ($attributeName == 'color') { | |||
if (preg_match('/rgb\s*\(/', $attributeValue)) { | |||
$this->$attributeName = $this->rgbToColour($attributeValue); | |||
} elseif (strpos(trim($attributeValue), '#') === 0) { | |||
$this->$attributeName = ltrim($attributeValue, '#'); | |||
} else { | |||
$this->$attributeName = $this->colourNameLookup($attributeValue); | |||
} | |||
} else { | |||
$this->$attributeName = $attributeValue; | |||
} | |||
} | |||
} | |||
protected function endFontTag() | |||
{ | |||
$this->face = $this->size = $this->color = null; | |||
} | |||
protected function startBoldTag() | |||
{ | |||
$this->bold = true; | |||
} | |||
protected function endBoldTag() | |||
{ | |||
$this->bold = false; | |||
} | |||
protected function startItalicTag() | |||
{ | |||
$this->italic = true; | |||
} | |||
protected function endItalicTag() | |||
{ | |||
$this->italic = false; | |||
} | |||
protected function startUnderlineTag() | |||
{ | |||
$this->underline = true; | |||
} | |||
protected function endUnderlineTag() | |||
{ | |||
$this->underline = false; | |||
} | |||
protected function startSubscriptTag() | |||
{ | |||
$this->subscript = true; | |||
} | |||
protected function endSubscriptTag() | |||
{ | |||
$this->subscript = false; | |||
} | |||
protected function startSuperscriptTag() | |||
{ | |||
$this->superscript = true; | |||
} | |||
protected function endSuperscriptTag() | |||
{ | |||
$this->superscript = false; | |||
} | |||
protected function startStrikethruTag() | |||
{ | |||
$this->strikethrough = true; | |||
} | |||
protected function endStrikethruTag() | |||
{ | |||
$this->strikethrough = false; | |||
} | |||
protected function breakTag() | |||
{ | |||
$this->stringData .= "\n"; | |||
} | |||
protected function parseTextNode(DOMText $textNode) | |||
{ | |||
$domText = preg_replace( | |||
'/\s+/u', | |||
' ', | |||
str_replace(array("\r", "\n"), ' ', $textNode->nodeValue) | |||
); | |||
$this->stringData .= $domText; | |||
$this->buildTextRun(); | |||
} | |||
protected function handleCallback($element, $callbackTag, $callbacks) | |||
{ | |||
if (isset($callbacks[$callbackTag])) { | |||
$elementHandler = $callbacks[$callbackTag]; | |||
if (method_exists($this, $elementHandler)) { | |||
call_user_func(array($this, $elementHandler), $element); | |||
} | |||
} | |||
} | |||
protected function parseElementNode(DOMElement $element) | |||
{ | |||
$callbackTag = strtolower($element->nodeName); | |||
$this->stack[] = $callbackTag; | |||
$this->handleCallback($element, $callbackTag, $this->startTagCallbacks); | |||
$this->parseElements($element); | |||
array_pop($this->stack); | |||
$this->handleCallback($element, $callbackTag, $this->endTagCallbacks); | |||
} | |||
protected function parseElements(DOMNode $element) | |||
{ | |||
foreach ($element->childNodes as $child) { | |||
if ($child instanceof DOMText) { | |||
$this->parseTextNode($child); | |||
} elseif ($child instanceof DOMElement) { | |||
$this->parseElementNode($child); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,34 @@ | |||
<?php | |||
/** | |||
* PHPExcel_IComparable | |||
* | |||
* 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
interface PHPExcel_IComparable | |||
{ | |||
/** | |||
* Get hash code | |||
* | |||
* @return string Hash code | |||
*/ | |||
public function getHashCode(); | |||
} |
@ -0,0 +1,289 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_IOFactory | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_IOFactory | |||
{ | |||
/** | |||
* Search locations | |||
* | |||
* @var array | |||
* @access private | |||
* @static | |||
*/ | |||
private static $searchLocations = array( | |||
array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), | |||
array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) | |||
); | |||
/** | |||
* Autoresolve classes | |||
* | |||
* @var array | |||
* @access private | |||
* @static | |||
*/ | |||
private static $autoResolveClasses = array( | |||
'Excel2007', | |||
'Excel5', | |||
'Excel2003XML', | |||
'OOCalc', | |||
'SYLK', | |||
'Gnumeric', | |||
'HTML', | |||
'CSV', | |||
); | |||
/** | |||
* Private constructor for PHPExcel_IOFactory | |||
*/ | |||
private function __construct() | |||
{ | |||
} | |||
/** | |||
* Get search locations | |||
* | |||
* @static | |||
* @access public | |||
* @return array | |||
*/ | |||
public static function getSearchLocations() | |||
{ | |||
return self::$searchLocations; | |||
} | |||
/** | |||
* Set search locations | |||
* | |||
* @static | |||
* @access public | |||
* @param array $value | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function setSearchLocations($value) | |||
{ | |||
if (is_array($value)) { | |||
self::$searchLocations = $value; | |||
} else { | |||
throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); | |||
} | |||
} | |||
/** | |||
* Add search location | |||
* | |||
* @static | |||
* @access public | |||
* @param string $type Example: IWriter | |||
* @param string $location Example: PHPExcel/Writer/{0}.php | |||
* @param string $classname Example: PHPExcel_Writer_[0] | |||
*/ | |||
public static function addSearchLocation($type = '', $location = '', $classname = '') | |||
{ | |||
self::$searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); | |||
} | |||
/** | |||
* Create PHPExcel_Writer_IWriter | |||
* | |||
* @static | |||
* @access public | |||
* @param PHPExcel $phpExcel | |||
* @param string $writerType Example: Excel2007 | |||
* @return PHPExcel_Writer_IWriter | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createWriter(PHPExcel $phpExcel, $writerType = '') | |||
{ | |||
// Search type | |||
$searchType = 'IWriter'; | |||
// Include class | |||
foreach (self::$searchLocations as $searchLocation) { | |||
if ($searchLocation['type'] == $searchType) { | |||
$className = str_replace('{0}', $writerType, $searchLocation['class']); | |||
$instance = new $className($phpExcel); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
} | |||
// Nothing found... | |||
throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); | |||
} | |||
/** | |||
* Create PHPExcel_Reader_IReader | |||
* | |||
* @static | |||
* @access public | |||
* @param string $readerType Example: Excel2007 | |||
* @return PHPExcel_Reader_IReader | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createReader($readerType = '') | |||
{ | |||
// Search type | |||
$searchType = 'IReader'; | |||
// Include class | |||
foreach (self::$searchLocations as $searchLocation) { | |||
if ($searchLocation['type'] == $searchType) { | |||
$className = str_replace('{0}', $readerType, $searchLocation['class']); | |||
$instance = new $className(); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
} | |||
// Nothing found... | |||
throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); | |||
} | |||
/** | |||
* Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function load($pFilename) | |||
{ | |||
$reader = self::createReaderForFile($pFilename); | |||
return $reader->load($pFilename); | |||
} | |||
/** | |||
* Identify file type using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file to identify | |||
* @return string | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function identify($pFilename) | |||
{ | |||
$reader = self::createReaderForFile($pFilename); | |||
$className = get_class($reader); | |||
$classType = explode('_', $className); | |||
unset($reader); | |||
return array_pop($classType); | |||
} | |||
/** | |||
* Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file | |||
* @return PHPExcel_Reader_IReader | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createReaderForFile($pFilename) | |||
{ | |||
// First, lucky guess by inspecting file extension | |||
$pathinfo = pathinfo($pFilename); | |||
$extensionType = null; | |||
if (isset($pathinfo['extension'])) { | |||
switch (strtolower($pathinfo['extension'])) { | |||
case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet | |||
case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded) | |||
case 'xltx': // Excel (OfficeOpenXML) Template | |||
case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded) | |||
$extensionType = 'Excel2007'; | |||
break; | |||
case 'xls': // Excel (BIFF) Spreadsheet | |||
case 'xlt': // Excel (BIFF) Template | |||
$extensionType = 'Excel5'; | |||
break; | |||
case 'ods': // Open/Libre Offic Calc | |||
case 'ots': // Open/Libre Offic Calc Template | |||
$extensionType = 'OOCalc'; | |||
break; | |||
case 'slk': | |||
$extensionType = 'SYLK'; | |||
break; | |||
case 'xml': // Excel 2003 SpreadSheetML | |||
$extensionType = 'Excel2003XML'; | |||
break; | |||
case 'gnumeric': | |||
$extensionType = 'Gnumeric'; | |||
break; | |||
case 'htm': | |||
case 'html': | |||
$extensionType = 'HTML'; | |||
break; | |||
case 'csv': | |||
// Do nothing | |||
// We must not try to use CSV reader since it loads | |||
// all files including Excel files etc. | |||
break; | |||
default: | |||
break; | |||
} | |||
if ($extensionType !== null) { | |||
$reader = self::createReader($extensionType); | |||
// Let's see if we are lucky | |||
if (isset($reader) && $reader->canRead($pFilename)) { | |||
return $reader; | |||
} | |||
} | |||
} | |||
// If we reach here then "lucky guess" didn't give any result | |||
// Try walking through all the options in self::$autoResolveClasses | |||
foreach (self::$autoResolveClasses as $autoResolveClass) { | |||
// Ignore our original guess, we know that won't work | |||
if ($autoResolveClass !== $extensionType) { | |||
$reader = self::createReader($autoResolveClass); | |||
if ($reader->canRead($pFilename)) { | |||
return $reader; | |||
} | |||
} | |||
} | |||
throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); | |||
} | |||
} |
@ -0,0 +1,289 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_IOFactory | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_IOFactory | |||
{ | |||
/** | |||
* Search locations | |||
* | |||
* @var array | |||
* @access private | |||
* @static | |||
*/ | |||
private static $searchLocations = array( | |||
array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), | |||
array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) | |||
); | |||
/** | |||
* Autoresolve classes | |||
* | |||
* @var array | |||
* @access private | |||
* @static | |||
*/ | |||
private static $autoResolveClasses = array( | |||
'Excel2007', | |||
'Excel5', | |||
'Excel2003XML', | |||
'OOCalc', | |||
'SYLK', | |||
'Gnumeric', | |||
'HTML', | |||
'CSV', | |||
); | |||
/** | |||
* Private constructor for PHPExcel_IOFactory | |||
*/ | |||
private function __construct() | |||
{ | |||
} | |||
/** | |||
* Get search locations | |||
* | |||
* @static | |||
* @access public | |||
* @return array | |||
*/ | |||
public static function getSearchLocations() | |||
{ | |||
return self::$searchLocations; | |||
} | |||
/** | |||
* Set search locations | |||
* | |||
* @static | |||
* @access public | |||
* @param array $value | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function setSearchLocations($value) | |||
{ | |||
if (is_array($value)) { | |||
self::$searchLocations = $value; | |||
} else { | |||
throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); | |||
} | |||
} | |||
/** | |||
* Add search location | |||
* | |||
* @static | |||
* @access public | |||
* @param string $type Example: IWriter | |||
* @param string $location Example: PHPExcel/Writer/{0}.php | |||
* @param string $classname Example: PHPExcel_Writer_{0} | |||
*/ | |||
public static function addSearchLocation($type = '', $location = '', $classname = '') | |||
{ | |||
self::$searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); | |||
} | |||
/** | |||
* Create PHPExcel_Writer_IWriter | |||
* | |||
* @static | |||
* @access public | |||
* @param PHPExcel $phpExcel | |||
* @param string $writerType Example: Excel2007 | |||
* @return PHPExcel_Writer_IWriter | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createWriter(PHPExcel $phpExcel, $writerType = '') | |||
{ | |||
// Search type | |||
$searchType = 'IWriter'; | |||
// Include class | |||
foreach (self::$searchLocations as $searchLocation) { | |||
if ($searchLocation['type'] == $searchType) { | |||
$className = str_replace('{0}', $writerType, $searchLocation['class']); | |||
$instance = new $className($phpExcel); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
} | |||
// Nothing found... | |||
throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); | |||
} | |||
/** | |||
* Create PHPExcel_Reader_IReader | |||
* | |||
* @static | |||
* @access public | |||
* @param string $readerType Example: Excel2007 | |||
* @return PHPExcel_Reader_IReader | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createReader($readerType = '') | |||
{ | |||
// Search type | |||
$searchType = 'IReader'; | |||
// Include class | |||
foreach (self::$searchLocations as $searchLocation) { | |||
if ($searchLocation['type'] == $searchType) { | |||
$className = str_replace('{0}', $readerType, $searchLocation['class']); | |||
$instance = new $className(); | |||
if ($instance !== null) { | |||
return $instance; | |||
} | |||
} | |||
} | |||
// Nothing found... | |||
throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); | |||
} | |||
/** | |||
* Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function load($pFilename) | |||
{ | |||
$reader = self::createReaderForFile($pFilename); | |||
return $reader->load($pFilename); | |||
} | |||
/** | |||
* Identify file type using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file to identify | |||
* @return string | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function identify($pFilename) | |||
{ | |||
$reader = self::createReaderForFile($pFilename); | |||
$className = get_class($reader); | |||
$classType = explode('_', $className); | |||
unset($reader); | |||
return array_pop($classType); | |||
} | |||
/** | |||
* Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution | |||
* | |||
* @static | |||
* @access public | |||
* @param string $pFilename The name of the spreadsheet file | |||
* @return PHPExcel_Reader_IReader | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public static function createReaderForFile($pFilename) | |||
{ | |||
// First, lucky guess by inspecting file extension | |||
$pathinfo = pathinfo($pFilename); | |||
$extensionType = null; | |||
if (isset($pathinfo['extension'])) { | |||
switch (strtolower($pathinfo['extension'])) { | |||
case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet | |||
case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded) | |||
case 'xltx': // Excel (OfficeOpenXML) Template | |||
case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded) | |||
$extensionType = 'Excel2007'; | |||
break; | |||
case 'xls': // Excel (BIFF) Spreadsheet | |||
case 'xlt': // Excel (BIFF) Template | |||
$extensionType = 'Excel5'; | |||
break; | |||
case 'ods': // Open/Libre Offic Calc | |||
case 'ots': // Open/Libre Offic Calc Template | |||
$extensionType = 'OOCalc'; | |||
break; | |||
case 'slk': | |||
$extensionType = 'SYLK'; | |||
break; | |||
case 'xml': // Excel 2003 SpreadSheetML | |||
$extensionType = 'Excel2003XML'; | |||
break; | |||
case 'gnumeric': | |||
$extensionType = 'Gnumeric'; | |||
break; | |||
case 'htm': | |||
case 'html': | |||
$extensionType = 'HTML'; | |||
break; | |||
case 'csv': | |||
// Do nothing | |||
// We must not try to use CSV reader since it loads | |||
// all files including Excel files etc. | |||
break; | |||
default: | |||
break; | |||
} | |||
if ($extensionType !== null) { | |||
$reader = self::createReader($extensionType); | |||
// Let's see if we are lucky | |||
if (isset($reader) && $reader->canRead($pFilename)) { | |||
return $reader; | |||
} | |||
} | |||
} | |||
// If we reach here then "lucky guess" didn't give any result | |||
// Try walking through all the options in self::$autoResolveClasses | |||
foreach (self::$autoResolveClasses as $autoResolveClass) { | |||
// Ignore our original guess, we know that won't work | |||
if ($autoResolveClass !== $extensionType) { | |||
$reader = self::createReader($autoResolveClass); | |||
if ($reader->canRead($pFilename)) { | |||
return $reader; | |||
} | |||
} | |||
} | |||
throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); | |||
} | |||
} |
@ -0,0 +1,249 @@ | |||
<?php | |||
/** | |||
* PHPExcel_NamedRange | |||
* | |||
* Copyright (c) 2006 - 2015 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 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_NamedRange | |||
{ | |||
/** | |||
* Range name | |||
* | |||
* @var string | |||
*/ | |||
private $name; | |||
/** | |||
* Worksheet on which the named range can be resolved | |||
* | |||
* @var PHPExcel_Worksheet | |||
*/ | |||
private $worksheet; | |||
/** | |||
* Range of the referenced cells | |||
* | |||
* @var string | |||
*/ | |||
private $range; | |||
/** | |||
* Is the named range local? (i.e. can only be used on $this->worksheet) | |||
* | |||
* @var bool | |||
*/ | |||
private $localOnly; | |||
/** | |||
* Scope | |||
* | |||
* @var PHPExcel_Worksheet | |||
*/ | |||
private $scope; | |||
/** | |||
* Create a new NamedRange | |||
* | |||
* @param string $pName | |||
* @param PHPExcel_Worksheet $pWorksheet | |||
* @param string $pRange | |||
* @param bool $pLocalOnly | |||
* @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. | |||
* @throws PHPExcel_Exception | |||
*/ | |||
public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) | |||
{ | |||
// Validate data | |||
if (($pName === null) || ($pWorksheet === null) || ($pRange === null)) { | |||
throw new PHPExcel_Exception('Parameters can not be null.'); | |||
} | |||
// Set local members | |||
$this->name = $pName; | |||
$this->worksheet = $pWorksheet; | |||
$this->range = $pRange; | |||
$this->localOnly = $pLocalOnly; | |||
$this->scope = ($pLocalOnly == true) ? (($pScope == null) ? $pWorksheet : $pScope) : null; | |||
} | |||
/** | |||
* Get name | |||
* | |||
* @return string | |||
*/ | |||
public function getName() | |||
{ | |||
return $this->name; | |||
} | |||
/** | |||
* Set name | |||
* | |||
* @param string $value | |||
* @return PHPExcel_NamedRange | |||
*/ | |||
public function setName($value = null) | |||
{ | |||
if ($value !== null) { | |||
// Old title | |||
$oldTitle = $this->name; | |||
// Re-attach | |||
if ($this->worksheet !== null) { | |||
$this->worksheet->getParent()->removeNamedRange($this->name, $this->worksheet); | |||
} | |||
$this->name = $value; | |||
if ($this->worksheet !== null) { | |||
$this->worksheet->getParent()->addNamedRange($this); | |||
} | |||
// New title | |||
$newTitle = $this->name; | |||
PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->worksheet->getParent(), $oldTitle, $newTitle); | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get worksheet | |||
* | |||
* @return PHPExcel_Worksheet | |||
*/ | |||
public function getWorksheet() | |||
{ | |||
return $this->worksheet; | |||
} | |||
/** | |||
* Set worksheet | |||
* | |||
* @param PHPExcel_Worksheet $value | |||
* @return PHPExcel_NamedRange | |||
*/ | |||
public function setWorksheet(PHPExcel_Worksheet $value = null) | |||
{ | |||
if ($value !== null) { | |||
$this->worksheet = $value; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get range | |||
* | |||
* @return string | |||
*/ | |||
public function getRange() | |||
{ | |||
return $this->range; | |||
} | |||
/** | |||
* Set range | |||
* | |||
* @param string $value | |||
* @return PHPExcel_NamedRange | |||
*/ | |||
public function setRange($value = null) | |||
{ | |||
if ($value !== null) { | |||
$this->range = $value; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get localOnly | |||
* | |||
* @return bool | |||
*/ | |||
public function getLocalOnly() | |||
{ | |||
return $this->localOnly; | |||
} | |||
/** | |||
* Set localOnly | |||
* | |||
* @param bool $value | |||
* @return PHPExcel_NamedRange | |||
*/ | |||
public function setLocalOnly($value = false) | |||
{ | |||
$this->localOnly = $value; | |||
$this->scope = $value ? $this->worksheet : null; | |||
return $this; | |||
} | |||
/** | |||
* Get scope | |||
* | |||
* @return PHPExcel_Worksheet|null | |||
*/ | |||
public function getScope() | |||
{ | |||
return $this->scope; | |||
} | |||
/** | |||
* Set scope | |||
* | |||
* @param PHPExcel_Worksheet|null $value | |||
* @return PHPExcel_NamedRange | |||
*/ | |||
public function setScope(PHPExcel_Worksheet $value = null) | |||
{ | |||
$this->scope = $value; | |||
$this->localOnly = ($value == null) ? false : true; | |||
return $this; | |||
} | |||
/** | |||
* Resolve a named range to a regular cell range | |||
* | |||
* @param string $pNamedRange Named range | |||
* @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope | |||
* @return PHPExcel_NamedRange | |||
*/ | |||
public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) | |||
{ | |||
return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet); | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if (is_object($value)) { | |||
$this->$key = clone $value; | |||
} else { | |||
$this->$key = $value; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,289 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Reader_Abstract | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
abstract class PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader | |||
{ | |||
/** | |||
* Read data only? | |||
* Identifies whether the Reader should only read data values for cells, and ignore any formatting information; | |||
* or whether it should read both data and formatting | |||
* | |||
* @var boolean | |||
*/ | |||
protected $readDataOnly = false; | |||
/** | |||
* Read empty cells? | |||
* Identifies whether the Reader should read data values for cells all cells, or should ignore cells containing | |||
* null value or empty string | |||
* | |||
* @var boolean | |||
*/ | |||
protected $readEmptyCells = true; | |||
/** | |||
* Read charts that are defined in the workbook? | |||
* Identifies whether the Reader should read the definitions for any charts that exist in the workbook; | |||
* | |||
* @var boolean | |||
*/ | |||
protected $includeCharts = false; | |||
/** | |||
* Restrict which sheets should be loaded? | |||
* This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. | |||
* | |||
* @var array of string | |||
*/ | |||
protected $loadSheetsOnly; | |||
/** | |||
* PHPExcel_Reader_IReadFilter instance | |||
* | |||
* @var PHPExcel_Reader_IReadFilter | |||
*/ | |||
protected $readFilter; | |||
protected $fileHandle = null; | |||
/** | |||
* Read data only? | |||
* If this is true, then the Reader will only read data values for cells, it will not read any formatting information. | |||
* If false (the default) it will read data and formatting. | |||
* | |||
* @return boolean | |||
*/ | |||
public function getReadDataOnly() | |||
{ | |||
return $this->readDataOnly; | |||
} | |||
/** | |||
* Set read data only | |||
* Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. | |||
* Set to false (the default) to advise the Reader to read both data and formatting for cells. | |||
* | |||
* @param boolean $pValue | |||
* | |||
* @return PHPExcel_Reader_IReader | |||
*/ | |||
public function setReadDataOnly($pValue = false) | |||
{ | |||
$this->readDataOnly = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Read empty cells? | |||
* If this is true (the default), then the Reader will read data values for all cells, irrespective of value. | |||
* If false it will not read data for cells containing a null value or an empty string. | |||
* | |||
* @return boolean | |||
*/ | |||
public function getReadEmptyCells() | |||
{ | |||
return $this->readEmptyCells; | |||
} | |||
/** | |||
* Set read empty cells | |||
* Set to true (the default) to advise the Reader read data values for all cells, irrespective of value. | |||
* Set to false to advise the Reader to ignore cells containing a null value or an empty string. | |||
* | |||
* @param boolean $pValue | |||
* | |||
* @return PHPExcel_Reader_IReader | |||
*/ | |||
public function setReadEmptyCells($pValue = true) | |||
{ | |||
$this->readEmptyCells = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Read charts in workbook? | |||
* If this is true, then the Reader will include any charts that exist in the workbook. | |||
* Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. | |||
* If false (the default) it will ignore any charts defined in the workbook file. | |||
* | |||
* @return boolean | |||
*/ | |||
public function getIncludeCharts() | |||
{ | |||
return $this->includeCharts; | |||
} | |||
/** | |||
* Set read charts in workbook | |||
* Set to true, to advise the Reader to include any charts that exist in the workbook. | |||
* Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. | |||
* Set to false (the default) to discard charts. | |||
* | |||
* @param boolean $pValue | |||
* | |||
* @return PHPExcel_Reader_IReader | |||
*/ | |||
public function setIncludeCharts($pValue = false) | |||
{ | |||
$this->includeCharts = (boolean) $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get which sheets to load | |||
* Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null | |||
* indicating that all worksheets in the workbook should be loaded. | |||
* | |||
* @return mixed | |||
*/ | |||
public function getLoadSheetsOnly() | |||
{ | |||
return $this->loadSheetsOnly; | |||
} | |||
/** | |||
* Set which sheets to load | |||
* | |||
* @param mixed $value | |||
* This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. | |||
* If NULL, then it tells the Reader to read all worksheets in the workbook | |||
* | |||
* @return PHPExcel_Reader_IReader | |||
*/ | |||
public function setLoadSheetsOnly($value = null) | |||
{ | |||
if ($value === null) { | |||
return $this->setLoadAllSheets(); | |||
} | |||
$this->loadSheetsOnly = is_array($value) ? $value : array($value); | |||
return $this; | |||
} | |||
/** | |||
* Set all sheets to load | |||
* Tells the Reader to load all worksheets from the workbook. | |||
* | |||
* @return PHPExcel_Reader_IReader | |||
*/ | |||
public function setLoadAllSheets() | |||
{ | |||
$this->loadSheetsOnly = null; | |||
return $this; | |||
} | |||
/** | |||
* Read filter | |||
* | |||
* @return PHPExcel_Reader_IReadFilter | |||
*/ | |||
public function getReadFilter() | |||
{ | |||
return $this->readFilter; | |||
} | |||
/** | |||
* Set read filter | |||
* | |||
* @param PHPExcel_Reader_IReadFilter $pValue | |||
* @return PHPExcel_Reader_IReader | |||
*/ | |||
public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) | |||
{ | |||
$this->readFilter = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Open file for reading | |||
* | |||
* @param string $pFilename | |||
* @throws PHPExcel_Reader_Exception | |||
* @return resource | |||
*/ | |||
protected function openFile($pFilename) | |||
{ | |||
// Check if file exists | |||
if (!file_exists($pFilename) || !is_readable($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
// Open file | |||
$this->fileHandle = fopen($pFilename, 'r'); | |||
if ($this->fileHandle === false) { | |||
throw new PHPExcel_Reader_Exception("Could not open file " . $pFilename . " for reading."); | |||
} | |||
} | |||
/** | |||
* Can the current PHPExcel_Reader_IReader read the file? | |||
* | |||
* @param string $pFilename | |||
* @return boolean | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function canRead($pFilename) | |||
{ | |||
// Check if file exists | |||
try { | |||
$this->openFile($pFilename); | |||
} catch (Exception $e) { | |||
return false; | |||
} | |||
$readable = $this->isValidFormat(); | |||
fclose($this->fileHandle); | |||
return $readable; | |||
} | |||
/** | |||
* Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks | |||
* | |||
* @param string $xml | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function securityScan($xml) | |||
{ | |||
$pattern = '/\\0?' . implode('\\0?', str_split('<!DOCTYPE')) . '\\0?/'; | |||
if (preg_match($pattern, $xml)) { | |||
throw new PHPExcel_Reader_Exception('Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks'); | |||
} | |||
return $xml; | |||
} | |||
/** | |||
* Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks | |||
* | |||
* @param string $filestream | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function securityScanFile($filestream) | |||
{ | |||
return $this->securityScan(file_get_contents($filestream)); | |||
} | |||
} |
@ -0,0 +1,406 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Reader_CSV | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_CSV extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader | |||
{ | |||
/** | |||
* Input encoding | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
private $inputEncoding = 'UTF-8'; | |||
/** | |||
* Delimiter | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
private $delimiter = ','; | |||
/** | |||
* Enclosure | |||
* | |||
* @access private | |||
* @var string | |||
*/ | |||
private $enclosure = '"'; | |||
/** | |||
* Sheet index to read | |||
* | |||
* @access private | |||
* @var int | |||
*/ | |||
private $sheetIndex = 0; | |||
/** | |||
* Load rows contiguously | |||
* | |||
* @access private | |||
* @var int | |||
*/ | |||
private $contiguous = false; | |||
/** | |||
* Row counter for loading rows contiguously | |||
* | |||
* @var int | |||
*/ | |||
private $contiguousRow = -1; | |||
/** | |||
* Create a new PHPExcel_Reader_CSV | |||
*/ | |||
public function __construct() | |||
{ | |||
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter(); | |||
} | |||
/** | |||
* Validate that the current file is a CSV file | |||
* | |||
* @return boolean | |||
*/ | |||
protected function isValidFormat() | |||
{ | |||
return true; | |||
} | |||
/** | |||
* Set input encoding | |||
* | |||
* @param string $pValue Input encoding | |||
*/ | |||
public function setInputEncoding($pValue = 'UTF-8') | |||
{ | |||
$this->inputEncoding = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get input encoding | |||
* | |||
* @return string | |||
*/ | |||
public function getInputEncoding() | |||
{ | |||
return $this->inputEncoding; | |||
} | |||
/** | |||
* Move filepointer past any BOM marker | |||
* | |||
*/ | |||
protected function skipBOM() | |||
{ | |||
rewind($this->fileHandle); | |||
switch ($this->inputEncoding) { | |||
case 'UTF-8': | |||
fgets($this->fileHandle, 4) == "\xEF\xBB\xBF" ? | |||
fseek($this->fileHandle, 3) : fseek($this->fileHandle, 0); | |||
break; | |||
case 'UTF-16LE': | |||
fgets($this->fileHandle, 3) == "\xFF\xFE" ? | |||
fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0); | |||
break; | |||
case 'UTF-16BE': | |||
fgets($this->fileHandle, 3) == "\xFE\xFF" ? | |||
fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0); | |||
break; | |||
case 'UTF-32LE': | |||
fgets($this->fileHandle, 5) == "\xFF\xFE\x00\x00" ? | |||
fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0); | |||
break; | |||
case 'UTF-32BE': | |||
fgets($this->fileHandle, 5) == "\x00\x00\xFE\xFF" ? | |||
fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
/** | |||
* Identify any separator that is explicitly set in the file | |||
* | |||
*/ | |||
protected function checkSeparator() | |||
{ | |||
$line = fgets($this->fileHandle); | |||
if ($line === false) { | |||
return; | |||
} | |||
if ((strlen(trim($line, "\r\n")) == 5) && (stripos($line, 'sep=') === 0)) { | |||
$this->delimiter = substr($line, 4, 1); | |||
return; | |||
} | |||
return $this->skipBOM(); | |||
} | |||
/** | |||
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) | |||
* | |||
* @param string $pFilename | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function listWorksheetInfo($pFilename) | |||
{ | |||
// Open file | |||
$this->openFile($pFilename); | |||
if (!$this->isValidFormat()) { | |||
fclose($this->fileHandle); | |||
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); | |||
} | |||
$fileHandle = $this->fileHandle; | |||
// Skip BOM, if any | |||
$this->skipBOM(); | |||
$this->checkSeparator(); | |||
$escapeEnclosures = array( "\\" . $this->enclosure, $this->enclosure . $this->enclosure ); | |||
$worksheetInfo = array(); | |||
$worksheetInfo[0]['worksheetName'] = 'Worksheet'; | |||
$worksheetInfo[0]['lastColumnLetter'] = 'A'; | |||
$worksheetInfo[0]['lastColumnIndex'] = 0; | |||
$worksheetInfo[0]['totalRows'] = 0; | |||
$worksheetInfo[0]['totalColumns'] = 0; | |||
// Loop through each line of the file in turn | |||
while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) { | |||
$worksheetInfo[0]['totalRows']++; | |||
$worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1); | |||
} | |||
$worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); | |||
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; | |||
// Close file | |||
fclose($fileHandle); | |||
return $worksheetInfo; | |||
} | |||
/** | |||
* Loads PHPExcel from file | |||
* | |||
* @param string $pFilename | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function load($pFilename) | |||
{ | |||
// Create new PHPExcel | |||
$objPHPExcel = new PHPExcel(); | |||
// Load into this instance | |||
return $this->loadIntoExisting($pFilename, $objPHPExcel); | |||
} | |||
/** | |||
* Loads PHPExcel from file into PHPExcel instance | |||
* | |||
* @param string $pFilename | |||
* @param PHPExcel $objPHPExcel | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) | |||
{ | |||
$lineEnding = ini_get('auto_detect_line_endings'); | |||
ini_set('auto_detect_line_endings', true); | |||
// Open file | |||
$this->openFile($pFilename); | |||
if (!$this->isValidFormat()) { | |||
fclose($this->fileHandle); | |||
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); | |||
} | |||
$fileHandle = $this->fileHandle; | |||
// Skip BOM, if any | |||
$this->skipBOM(); | |||
$this->checkSeparator(); | |||
// Create new PHPExcel object | |||
while ($objPHPExcel->getSheetCount() <= $this->sheetIndex) { | |||
$objPHPExcel->createSheet(); | |||
} | |||
$sheet = $objPHPExcel->setActiveSheetIndex($this->sheetIndex); | |||
$escapeEnclosures = array( "\\" . $this->enclosure, | |||
$this->enclosure . $this->enclosure | |||
); | |||
// Set our starting row based on whether we're in contiguous mode or not | |||
$currentRow = 1; | |||
if ($this->contiguous) { | |||
$currentRow = ($this->contiguousRow == -1) ? $sheet->getHighestRow(): $this->contiguousRow; | |||
} | |||
// Loop through each line of the file in turn | |||
while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) { | |||
$columnLetter = 'A'; | |||
foreach ($rowData as $rowDatum) { | |||
if ($rowDatum != '' && $this->readFilter->readCell($columnLetter, $currentRow)) { | |||
// Unescape enclosures | |||
$rowDatum = str_replace($escapeEnclosures, $this->enclosure, $rowDatum); | |||
// Convert encoding if necessary | |||
if ($this->inputEncoding !== 'UTF-8') { | |||
$rowDatum = PHPExcel_Shared_String::ConvertEncoding($rowDatum, 'UTF-8', $this->inputEncoding); | |||
} | |||
// Set cell value | |||
$sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum); | |||
} | |||
++$columnLetter; | |||
} | |||
++$currentRow; | |||
} | |||
// Close file | |||
fclose($fileHandle); | |||
if ($this->contiguous) { | |||
$this->contiguousRow = $currentRow; | |||
} | |||
ini_set('auto_detect_line_endings', $lineEnding); | |||
// Return | |||
return $objPHPExcel; | |||
} | |||
/** | |||
* Get delimiter | |||
* | |||
* @return string | |||
*/ | |||
public function getDelimiter() | |||
{ | |||
return $this->delimiter; | |||
} | |||
/** | |||
* Set delimiter | |||
* | |||
* @param string $pValue Delimiter, defaults to , | |||
* @return PHPExcel_Reader_CSV | |||
*/ | |||
public function setDelimiter($pValue = ',') | |||
{ | |||
$this->delimiter = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get enclosure | |||
* | |||
* @return string | |||
*/ | |||
public function getEnclosure() | |||
{ | |||
return $this->enclosure; | |||
} | |||
/** | |||
* Set enclosure | |||
* | |||
* @param string $pValue Enclosure, defaults to " | |||
* @return PHPExcel_Reader_CSV | |||
*/ | |||
public function setEnclosure($pValue = '"') | |||
{ | |||
if ($pValue == '') { | |||
$pValue = '"'; | |||
} | |||
$this->enclosure = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Get sheet index | |||
* | |||
* @return integer | |||
*/ | |||
public function getSheetIndex() | |||
{ | |||
return $this->sheetIndex; | |||
} | |||
/** | |||
* Set sheet index | |||
* | |||
* @param integer $pValue Sheet index | |||
* @return PHPExcel_Reader_CSV | |||
*/ | |||
public function setSheetIndex($pValue = 0) | |||
{ | |||
$this->sheetIndex = $pValue; | |||
return $this; | |||
} | |||
/** | |||
* Set Contiguous | |||
* | |||
* @param boolean $contiguous | |||
*/ | |||
public function setContiguous($contiguous = false) | |||
{ | |||
$this->contiguous = (bool) $contiguous; | |||
if (!$contiguous) { | |||
$this->contiguousRow = -1; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Get Contiguous | |||
* | |||
* @return boolean | |||
*/ | |||
public function getContiguous() | |||
{ | |||
return $this->contiguous; | |||
} | |||
} |
@ -0,0 +1,51 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Reader_DefaultReadFilter | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter | |||
{ | |||
/** | |||
* Should this cell be read? | |||
* | |||
* @param $column Column address (as a string value like "A", or "IV") | |||
* @param $row Row number | |||
* @param $worksheetName Optional worksheet name | |||
* @return boolean | |||
*/ | |||
public function readCell($column, $row, $worksheetName = '') | |||
{ | |||
return true; | |||
} | |||
} |
@ -0,0 +1,801 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Reader_Excel2003XML | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_Excel2003XML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader | |||
{ | |||
/** | |||
* Formats | |||
* | |||
* @var array | |||
*/ | |||
protected $styles = array(); | |||
/** | |||
* Character set used in the file | |||
* | |||
* @var string | |||
*/ | |||
protected $charSet = 'UTF-8'; | |||
/** | |||
* Create a new PHPExcel_Reader_Excel2003XML | |||
*/ | |||
public function __construct() | |||
{ | |||
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter(); | |||
} | |||
/** | |||
* Can the current PHPExcel_Reader_IReader read the file? | |||
* | |||
* @param string $pFilename | |||
* @return boolean | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function canRead($pFilename) | |||
{ | |||
// Office xmlns:o="urn:schemas-microsoft-com:office:office" | |||
// Excel xmlns:x="urn:schemas-microsoft-com:office:excel" | |||
// XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" | |||
// Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" | |||
// XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" | |||
// XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" | |||
// MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" | |||
// Rowset xmlns:z="#RowsetSchema" | |||
// | |||
$signature = array( | |||
'<?xml version="1.0"', | |||
'<?mso-application progid="Excel.Sheet"?>' | |||
); | |||
// Open file | |||
$this->openFile($pFilename); | |||
$fileHandle = $this->fileHandle; | |||
// Read sample data (first 2 KB will do) | |||
$data = fread($fileHandle, 2048); | |||
fclose($fileHandle); | |||
$valid = true; | |||
foreach ($signature as $match) { | |||
// every part of the signature must be present | |||
if (strpos($data, $match) === false) { | |||
$valid = false; | |||
break; | |||
} | |||
} | |||
// Retrieve charset encoding | |||
if (preg_match('/<?xml.*encoding=[\'"](.*?)[\'"].*?>/um', $data, $matches)) { | |||
$this->charSet = strtoupper($matches[1]); | |||
} | |||
// echo 'Character Set is ', $this->charSet,'<br />'; | |||
return $valid; | |||
} | |||
/** | |||
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object | |||
* | |||
* @param string $pFilename | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function listWorksheetNames($pFilename) | |||
{ | |||
// Check if file exists | |||
if (!file_exists($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
if (!$this->canRead($pFilename)) { | |||
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); | |||
} | |||
$worksheetNames = array(); | |||
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); | |||
$namespaces = $xml->getNamespaces(true); | |||
$xml_ss = $xml->children($namespaces['ss']); | |||
foreach ($xml_ss->Worksheet as $worksheet) { | |||
$worksheet_ss = $worksheet->attributes($namespaces['ss']); | |||
$worksheetNames[] = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet); | |||
} | |||
return $worksheetNames; | |||
} | |||
/** | |||
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) | |||
* | |||
* @param string $pFilename | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function listWorksheetInfo($pFilename) | |||
{ | |||
// Check if file exists | |||
if (!file_exists($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
$worksheetInfo = array(); | |||
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); | |||
$namespaces = $xml->getNamespaces(true); | |||
$worksheetID = 1; | |||
$xml_ss = $xml->children($namespaces['ss']); | |||
foreach ($xml_ss->Worksheet as $worksheet) { | |||
$worksheet_ss = $worksheet->attributes($namespaces['ss']); | |||
$tmpInfo = array(); | |||
$tmpInfo['worksheetName'] = ''; | |||
$tmpInfo['lastColumnLetter'] = 'A'; | |||
$tmpInfo['lastColumnIndex'] = 0; | |||
$tmpInfo['totalRows'] = 0; | |||
$tmpInfo['totalColumns'] = 0; | |||
if (isset($worksheet_ss['Name'])) { | |||
$tmpInfo['worksheetName'] = (string) $worksheet_ss['Name']; | |||
} else { | |||
$tmpInfo['worksheetName'] = "Worksheet_[$worksheetID]"; | |||
} | |||
if (isset($worksheet->Table->Row)) { | |||
$rowIndex = 0; | |||
foreach ($worksheet->Table->Row as $rowData) { | |||
$columnIndex = 0; | |||
$rowHasData = false; | |||
foreach ($rowData->Cell as $cell) { | |||
if (isset($cell->Data)) { | |||
$tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); | |||
$rowHasData = true; | |||
} | |||
++$columnIndex; | |||
} | |||
++$rowIndex; | |||
if ($rowHasData) { | |||
$tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); | |||
} | |||
} | |||
} | |||
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); | |||
$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; | |||
$worksheetInfo[] = $tmpInfo; | |||
++$worksheetID; | |||
} | |||
return $worksheetInfo; | |||
} | |||
/** | |||
* Loads PHPExcel from file | |||
* | |||
* @param string $pFilename | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function load($pFilename) | |||
{ | |||
// Create new PHPExcel | |||
$objPHPExcel = new PHPExcel(); | |||
$objPHPExcel->removeSheetByIndex(0); | |||
// Load into this instance | |||
return $this->loadIntoExisting($pFilename, $objPHPExcel); | |||
} | |||
protected static function identifyFixedStyleValue($styleList, &$styleAttributeValue) | |||
{ | |||
$styleAttributeValue = strtolower($styleAttributeValue); | |||
foreach ($styleList as $style) { | |||
if ($styleAttributeValue == strtolower($style)) { | |||
$styleAttributeValue = $style; | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* pixel units to excel width units(units of 1/256th of a character width) | |||
* @param pxs | |||
* @return | |||
*/ | |||
protected static function pixel2WidthUnits($pxs) | |||
{ | |||
$UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); | |||
$widthUnits = 256 * ($pxs / 7); | |||
$widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; | |||
return $widthUnits; | |||
} | |||
/** | |||
* excel width units(units of 1/256th of a character width) to pixel units | |||
* @param widthUnits | |||
* @return | |||
*/ | |||
protected static function widthUnits2Pixel($widthUnits) | |||
{ | |||
$pixels = ($widthUnits / 256) * 7; | |||
$offsetWidthUnits = $widthUnits % 256; | |||
$pixels += round($offsetWidthUnits / (256 / 7)); | |||
return $pixels; | |||
} | |||
protected static function hex2str($hex) | |||
{ | |||
return chr(hexdec($hex[1])); | |||
} | |||
/** | |||
* Loads PHPExcel from file into PHPExcel instance | |||
* | |||
* @param string $pFilename | |||
* @param PHPExcel $objPHPExcel | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) | |||
{ | |||
$fromFormats = array('\-', '\ '); | |||
$toFormats = array('-', ' '); | |||
$underlineStyles = array ( | |||
PHPExcel_Style_Font::UNDERLINE_NONE, | |||
PHPExcel_Style_Font::UNDERLINE_DOUBLE, | |||
PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, | |||
PHPExcel_Style_Font::UNDERLINE_SINGLE, | |||
PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING | |||
); | |||
$verticalAlignmentStyles = array ( | |||
PHPExcel_Style_Alignment::VERTICAL_BOTTOM, | |||
PHPExcel_Style_Alignment::VERTICAL_TOP, | |||
PHPExcel_Style_Alignment::VERTICAL_CENTER, | |||
PHPExcel_Style_Alignment::VERTICAL_JUSTIFY | |||
); | |||
$horizontalAlignmentStyles = array ( | |||
PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, | |||
PHPExcel_Style_Alignment::HORIZONTAL_LEFT, | |||
PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, | |||
PHPExcel_Style_Alignment::HORIZONTAL_CENTER, | |||
PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, | |||
PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY | |||
); | |||
$timezoneObj = new DateTimeZone('Europe/London'); | |||
$GMT = new DateTimeZone('UTC'); | |||
// Check if file exists | |||
if (!file_exists($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
if (!$this->canRead($pFilename)) { | |||
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); | |||
} | |||
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); | |||
$namespaces = $xml->getNamespaces(true); | |||
$docProps = $objPHPExcel->getProperties(); | |||
if (isset($xml->DocumentProperties[0])) { | |||
foreach ($xml->DocumentProperties[0] as $propertyName => $propertyValue) { | |||
switch ($propertyName) { | |||
case 'Title': | |||
$docProps->setTitle(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Subject': | |||
$docProps->setSubject(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Author': | |||
$docProps->setCreator(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Created': | |||
$creationDate = strtotime($propertyValue); | |||
$docProps->setCreated($creationDate); | |||
break; | |||
case 'LastAuthor': | |||
$docProps->setLastModifiedBy(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'LastSaved': | |||
$lastSaveDate = strtotime($propertyValue); | |||
$docProps->setModified($lastSaveDate); | |||
break; | |||
case 'Company': | |||
$docProps->setCompany(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Category': | |||
$docProps->setCategory(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Manager': | |||
$docProps->setManager(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Keywords': | |||
$docProps->setKeywords(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Description': | |||
$docProps->setDescription(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
} | |||
} | |||
} | |||
if (isset($xml->CustomDocumentProperties)) { | |||
foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { | |||
$propertyAttributes = $propertyValue->attributes($namespaces['dt']); | |||
$propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/', 'PHPExcel_Reader_Excel2003XML::hex2str', $propertyName); | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_UNKNOWN; | |||
switch ((string) $propertyAttributes) { | |||
case 'string': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; | |||
$propertyValue = trim($propertyValue); | |||
break; | |||
case 'boolean': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; | |||
$propertyValue = (bool) $propertyValue; | |||
break; | |||
case 'integer': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_INTEGER; | |||
$propertyValue = intval($propertyValue); | |||
break; | |||
case 'float': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; | |||
$propertyValue = floatval($propertyValue); | |||
break; | |||
case 'dateTime.tz': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; | |||
$propertyValue = strtotime(trim($propertyValue)); | |||
break; | |||
} | |||
$docProps->setCustomProperty($propertyName, $propertyValue, $propertyType); | |||
} | |||
} | |||
foreach ($xml->Styles[0] as $style) { | |||
$style_ss = $style->attributes($namespaces['ss']); | |||
$styleID = (string) $style_ss['ID']; | |||
// echo 'Style ID = '.$styleID.'<br />'; | |||
$this->styles[$styleID] = (isset($this->styles['Default'])) ? $this->styles['Default'] : array(); | |||
foreach ($style as $styleType => $styleData) { | |||
$styleAttributes = $styleData->attributes($namespaces['ss']); | |||
// echo $styleType.'<br />'; | |||
switch ($styleType) { | |||
case 'Alignment': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
$styleAttributeValue = (string) $styleAttributeValue; | |||
switch ($styleAttributeKey) { | |||
case 'Vertical': | |||
if (self::identifyFixedStyleValue($verticalAlignmentStyles, $styleAttributeValue)) { | |||
$this->styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; | |||
} | |||
break; | |||
case 'Horizontal': | |||
if (self::identifyFixedStyleValue($horizontalAlignmentStyles, $styleAttributeValue)) { | |||
$this->styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; | |||
} | |||
break; | |||
case 'WrapText': | |||
$this->styles[$styleID]['alignment']['wrap'] = true; | |||
break; | |||
} | |||
} | |||
break; | |||
case 'Borders': | |||
foreach ($styleData->Border as $borderStyle) { | |||
$borderAttributes = $borderStyle->attributes($namespaces['ss']); | |||
$thisBorder = array(); | |||
foreach ($borderAttributes as $borderStyleKey => $borderStyleValue) { | |||
// echo $borderStyleKey.' = '.$borderStyleValue.'<br />'; | |||
switch ($borderStyleKey) { | |||
case 'LineStyle': | |||
$thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; | |||
// $thisBorder['style'] = $borderStyleValue; | |||
break; | |||
case 'Weight': | |||
// $thisBorder['style'] = $borderStyleValue; | |||
break; | |||
case 'Position': | |||
$borderPosition = strtolower($borderStyleValue); | |||
break; | |||
case 'Color': | |||
$borderColour = substr($borderStyleValue, 1); | |||
$thisBorder['color']['rgb'] = $borderColour; | |||
break; | |||
} | |||
} | |||
if (!empty($thisBorder)) { | |||
if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { | |||
$this->styles[$styleID]['borders'][$borderPosition] = $thisBorder; | |||
} | |||
} | |||
} | |||
break; | |||
case 'Font': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
$styleAttributeValue = (string) $styleAttributeValue; | |||
switch ($styleAttributeKey) { | |||
case 'FontName': | |||
$this->styles[$styleID]['font']['name'] = $styleAttributeValue; | |||
break; | |||
case 'Size': | |||
$this->styles[$styleID]['font']['size'] = $styleAttributeValue; | |||
break; | |||
case 'Color': | |||
$this->styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue, 1); | |||
break; | |||
case 'Bold': | |||
$this->styles[$styleID]['font']['bold'] = true; | |||
break; | |||
case 'Italic': | |||
$this->styles[$styleID]['font']['italic'] = true; | |||
break; | |||
case 'Underline': | |||
if (self::identifyFixedStyleValue($underlineStyles, $styleAttributeValue)) { | |||
$this->styles[$styleID]['font']['underline'] = $styleAttributeValue; | |||
} | |||
break; | |||
} | |||
} | |||
break; | |||
case 'Interior': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
switch ($styleAttributeKey) { | |||
case 'Color': | |||
$this->styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue, 1); | |||
break; | |||
} | |||
} | |||
break; | |||
case 'NumberFormat': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
$styleAttributeValue = str_replace($fromFormats, $toFormats, $styleAttributeValue); | |||
switch ($styleAttributeValue) { | |||
case 'Short Date': | |||
$styleAttributeValue = 'dd/mm/yyyy'; | |||
break; | |||
} | |||
if ($styleAttributeValue > '') { | |||
$this->styles[$styleID]['numberformat']['code'] = $styleAttributeValue; | |||
} | |||
} | |||
break; | |||
case 'Protection': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
} | |||
break; | |||
} | |||
} | |||
// print_r($this->styles[$styleID]); | |||
// echo '<hr />'; | |||
} | |||
// echo '<hr />'; | |||
$worksheetID = 0; | |||
$xml_ss = $xml->children($namespaces['ss']); | |||
foreach ($xml_ss->Worksheet as $worksheet) { | |||
$worksheet_ss = $worksheet->attributes($namespaces['ss']); | |||
if ((isset($this->loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && | |||
(!in_array($worksheet_ss['Name'], $this->loadSheetsOnly))) { | |||
continue; | |||
} | |||
// echo '<h3>Worksheet: ', $worksheet_ss['Name'],'<h3>'; | |||
// | |||
// Create new Worksheet | |||
$objPHPExcel->createSheet(); | |||
$objPHPExcel->setActiveSheetIndex($worksheetID); | |||
if (isset($worksheet_ss['Name'])) { | |||
$worksheetName = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet); | |||
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in | |||
// formula cells... during the load, all formulae should be correct, and we're simply bringing | |||
// the worksheet name in line with the formula, not the reverse | |||
$objPHPExcel->getActiveSheet()->setTitle($worksheetName, false); | |||
} | |||
$columnID = 'A'; | |||
if (isset($worksheet->Table->Column)) { | |||
foreach ($worksheet->Table->Column as $columnData) { | |||
$columnData_ss = $columnData->attributes($namespaces['ss']); | |||
if (isset($columnData_ss['Index'])) { | |||
$columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); | |||
} | |||
if (isset($columnData_ss['Width'])) { | |||
$columnWidth = $columnData_ss['Width']; | |||
// echo '<b>Setting column width for '.$columnID.' to '.$columnWidth.'</b><br />'; | |||
$objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); | |||
} | |||
++$columnID; | |||
} | |||
} | |||
$rowID = 1; | |||
if (isset($worksheet->Table->Row)) { | |||
$additionalMergedCells = 0; | |||
foreach ($worksheet->Table->Row as $rowData) { | |||
$rowHasData = false; | |||
$row_ss = $rowData->attributes($namespaces['ss']); | |||
if (isset($row_ss['Index'])) { | |||
$rowID = (integer) $row_ss['Index']; | |||
} | |||
// echo '<b>Row '.$rowID.'</b><br />'; | |||
$columnID = 'A'; | |||
foreach ($rowData->Cell as $cell) { | |||
$cell_ss = $cell->attributes($namespaces['ss']); | |||
if (isset($cell_ss['Index'])) { | |||
$columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); | |||
} | |||
$cellRange = $columnID.$rowID; | |||
if ($this->getReadFilter() !== null) { | |||
if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { | |||
continue; | |||
} | |||
} | |||
if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { | |||
$columnTo = $columnID; | |||
if (isset($cell_ss['MergeAcross'])) { | |||
$additionalMergedCells += (int)$cell_ss['MergeAcross']; | |||
$columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); | |||
} | |||
$rowTo = $rowID; | |||
if (isset($cell_ss['MergeDown'])) { | |||
$rowTo = $rowTo + $cell_ss['MergeDown']; | |||
} | |||
$cellRange .= ':'.$columnTo.$rowTo; | |||
$objPHPExcel->getActiveSheet()->mergeCells($cellRange); | |||
} | |||
$cellIsSet = $hasCalculatedValue = false; | |||
$cellDataFormula = ''; | |||
if (isset($cell_ss['Formula'])) { | |||
$cellDataFormula = $cell_ss['Formula']; | |||
// added this as a check for array formulas | |||
if (isset($cell_ss['ArrayRange'])) { | |||
$cellDataCSEFormula = $cell_ss['ArrayRange']; | |||
// echo "found an array formula at ".$columnID.$rowID."<br />"; | |||
} | |||
$hasCalculatedValue = true; | |||
} | |||
if (isset($cell->Data)) { | |||
$cellValue = $cellData = $cell->Data; | |||
$type = PHPExcel_Cell_DataType::TYPE_NULL; | |||
$cellData_ss = $cellData->attributes($namespaces['ss']); | |||
if (isset($cellData_ss['Type'])) { | |||
$cellDataType = $cellData_ss['Type']; | |||
switch ($cellDataType) { | |||
/* | |||
const TYPE_STRING = 's'; | |||
const TYPE_FORMULA = 'f'; | |||
const TYPE_NUMERIC = 'n'; | |||
const TYPE_BOOL = 'b'; | |||
const TYPE_NULL = 'null'; | |||
const TYPE_INLINE = 'inlineStr'; | |||
const TYPE_ERROR = 'e'; | |||
*/ | |||
case 'String': | |||
$cellValue = self::convertStringEncoding($cellValue, $this->charSet); | |||
$type = PHPExcel_Cell_DataType::TYPE_STRING; | |||
break; | |||
case 'Number': | |||
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
$cellValue = (float) $cellValue; | |||
if (floor($cellValue) == $cellValue) { | |||
$cellValue = (integer) $cellValue; | |||
} | |||
break; | |||
case 'Boolean': | |||
$type = PHPExcel_Cell_DataType::TYPE_BOOL; | |||
$cellValue = ($cellValue != 0); | |||
break; | |||
case 'DateTime': | |||
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
$cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); | |||
break; | |||
case 'Error': | |||
$type = PHPExcel_Cell_DataType::TYPE_ERROR; | |||
break; | |||
} | |||
} | |||
if ($hasCalculatedValue) { | |||
// echo 'FORMULA<br />'; | |||
$type = PHPExcel_Cell_DataType::TYPE_FORMULA; | |||
$columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); | |||
if (substr($cellDataFormula, 0, 3) == 'of:') { | |||
$cellDataFormula = substr($cellDataFormula, 3); | |||
// echo 'Before: ', $cellDataFormula,'<br />'; | |||
$temp = explode('"', $cellDataFormula); | |||
$key = false; | |||
foreach ($temp as &$value) { | |||
// Only replace in alternate array entries (i.e. non-quoted blocks) | |||
if ($key = !$key) { | |||
$value = str_replace(array('[.', '.', ']'), '', $value); | |||
} | |||
} | |||
} else { | |||
// Convert R1C1 style references to A1 style references (but only when not quoted) | |||
// echo 'Before: ', $cellDataFormula,'<br />'; | |||
$temp = explode('"', $cellDataFormula); | |||
$key = false; | |||
foreach ($temp as &$value) { | |||
// Only replace in alternate array entries (i.e. non-quoted blocks) | |||
if ($key = !$key) { | |||
preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/', $value, $cellReferences, PREG_SET_ORDER + PREG_OFFSET_CAPTURE); | |||
// Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way | |||
// through the formula from left to right. Reversing means that we work right to left.through | |||
// the formula | |||
$cellReferences = array_reverse($cellReferences); | |||
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, | |||
// then modify the formula to use that new reference | |||
foreach ($cellReferences as $cellReference) { | |||
$rowReference = $cellReference[2][0]; | |||
// Empty R reference is the current row | |||
if ($rowReference == '') { | |||
$rowReference = $rowID; | |||
} | |||
// Bracketed R references are relative to the current row | |||
if ($rowReference[0] == '[') { | |||
$rowReference = $rowID + trim($rowReference, '[]'); | |||
} | |||
$columnReference = $cellReference[4][0]; | |||
// Empty C reference is the current column | |||
if ($columnReference == '') { | |||
$columnReference = $columnNumber; | |||
} | |||
// Bracketed C references are relative to the current column | |||
if ($columnReference[0] == '[') { | |||
$columnReference = $columnNumber + trim($columnReference, '[]'); | |||
} | |||
$A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; | |||
$value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0])); | |||
} | |||
} | |||
} | |||
} | |||
unset($value); | |||
// Then rebuild the formula string | |||
$cellDataFormula = implode('"', $temp); | |||
// echo 'After: ', $cellDataFormula,'<br />'; | |||
} | |||
// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'<br />'; | |||
// | |||
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue), $type); | |||
if ($hasCalculatedValue) { | |||
// echo 'Formula result is '.$cellValue.'<br />'; | |||
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); | |||
} | |||
$cellIsSet = $rowHasData = true; | |||
} | |||
if (isset($cell->Comment)) { | |||
// echo '<b>comment found</b><br />'; | |||
$commentAttributes = $cell->Comment->attributes($namespaces['ss']); | |||
$author = 'unknown'; | |||
if (isset($commentAttributes->Author)) { | |||
$author = (string)$commentAttributes->Author; | |||
// echo 'Author: ', $author,'<br />'; | |||
} | |||
$node = $cell->Comment->Data->asXML(); | |||
// $annotation = str_replace('html:','',substr($node,49,-10)); | |||
// echo $annotation,'<br />'; | |||
$annotation = strip_tags($node); | |||
// echo 'Annotation: ', $annotation,'<br />'; | |||
$objPHPExcel->getActiveSheet()->getComment($columnID.$rowID)->setAuthor(self::convertStringEncoding($author, $this->charSet))->setText($this->parseRichText($annotation)); | |||
} | |||
if (($cellIsSet) && (isset($cell_ss['StyleID']))) { | |||
$style = (string) $cell_ss['StyleID']; | |||
// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'<br />'; | |||
if ((isset($this->styles[$style])) && (!empty($this->styles[$style]))) { | |||
// echo 'Cell '.$columnID.$rowID.'<br />'; | |||
// print_r($this->styles[$style]); | |||
// echo '<br />'; | |||
if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { | |||
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(null); | |||
} | |||
$objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->styles[$style]); | |||
} | |||
} | |||
++$columnID; | |||
while ($additionalMergedCells > 0) { | |||
++$columnID; | |||
$additionalMergedCells--; | |||
} | |||
} | |||
if ($rowHasData) { | |||
if (isset($row_ss['StyleID'])) { | |||
$rowStyle = $row_ss['StyleID']; | |||
} | |||
if (isset($row_ss['Height'])) { | |||
$rowHeight = $row_ss['Height']; | |||
// echo '<b>Setting row height to '.$rowHeight.'</b><br />'; | |||
$objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); | |||
} | |||
} | |||
++$rowID; | |||
} | |||
} | |||
++$worksheetID; | |||
} | |||
// Return | |||
return $objPHPExcel; | |||
} | |||
protected static function convertStringEncoding($string, $charset) | |||
{ | |||
if ($charset != 'UTF-8') { | |||
return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', $charset); | |||
} | |||
return $string; | |||
} | |||
protected function parseRichText($is = '') | |||
{ | |||
$value = new PHPExcel_RichText(); | |||
$value->createText(self::convertStringEncoding($is, $this->charSet)); | |||
return $value; | |||
} | |||
} |
@ -0,0 +1,801 @@ | |||
<?php | |||
/** PHPExcel root directory */ | |||
if (!defined('PHPEXCEL_ROOT')) { | |||
/** | |||
* @ignore | |||
*/ | |||
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); | |||
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); | |||
} | |||
/** | |||
* PHPExcel_Reader_Excel2003XML | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_Excel2003XML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader | |||
{ | |||
/** | |||
* Formats | |||
* | |||
* @var array | |||
*/ | |||
protected $styles = array(); | |||
/** | |||
* Character set used in the file | |||
* | |||
* @var string | |||
*/ | |||
protected $charSet = 'UTF-8'; | |||
/** | |||
* Create a new PHPExcel_Reader_Excel2003XML | |||
*/ | |||
public function __construct() | |||
{ | |||
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter(); | |||
} | |||
/** | |||
* Can the current PHPExcel_Reader_IReader read the file? | |||
* | |||
* @param string $pFilename | |||
* @return boolean | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function canRead($pFilename) | |||
{ | |||
// Office xmlns:o="urn:schemas-microsoft-com:office:office" | |||
// Excel xmlns:x="urn:schemas-microsoft-com:office:excel" | |||
// XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" | |||
// Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" | |||
// XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" | |||
// XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" | |||
// MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" | |||
// Rowset xmlns:z="#RowsetSchema" | |||
// | |||
$signature = array( | |||
'<?xml version="1.0"', | |||
'<?mso-application progid="Excel.Sheet"?>' | |||
); | |||
// Open file | |||
$this->openFile($pFilename); | |||
$fileHandle = $this->fileHandle; | |||
// Read sample data (first 2 KB will do) | |||
$data = fread($fileHandle, 2048); | |||
fclose($fileHandle); | |||
$valid = true; | |||
foreach ($signature as $match) { | |||
// every part of the signature must be present | |||
if (strpos($data, $match) === false) { | |||
$valid = false; | |||
break; | |||
} | |||
} | |||
// Retrieve charset encoding | |||
if (preg_match('/<?xml.*encoding=[\'"](.*?)[\'"].*?>/um', $data, $matches)) { | |||
$this->charSet = strtoupper($matches[1]); | |||
} | |||
// echo 'Character Set is ', $this->charSet,'<br />'; | |||
return $valid; | |||
} | |||
/** | |||
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object | |||
* | |||
* @param string $pFilename | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function listWorksheetNames($pFilename) | |||
{ | |||
// Check if file exists | |||
if (!file_exists($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
if (!$this->canRead($pFilename)) { | |||
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); | |||
} | |||
$worksheetNames = array(); | |||
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); | |||
$namespaces = $xml->getNamespaces(true); | |||
$xml_ss = $xml->children($namespaces['ss']); | |||
foreach ($xml_ss->Worksheet as $worksheet) { | |||
$worksheet_ss = $worksheet->attributes($namespaces['ss']); | |||
$worksheetNames[] = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet); | |||
} | |||
return $worksheetNames; | |||
} | |||
/** | |||
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) | |||
* | |||
* @param string $pFilename | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function listWorksheetInfo($pFilename) | |||
{ | |||
// Check if file exists | |||
if (!file_exists($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
$worksheetInfo = array(); | |||
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); | |||
$namespaces = $xml->getNamespaces(true); | |||
$worksheetID = 1; | |||
$xml_ss = $xml->children($namespaces['ss']); | |||
foreach ($xml_ss->Worksheet as $worksheet) { | |||
$worksheet_ss = $worksheet->attributes($namespaces['ss']); | |||
$tmpInfo = array(); | |||
$tmpInfo['worksheetName'] = ''; | |||
$tmpInfo['lastColumnLetter'] = 'A'; | |||
$tmpInfo['lastColumnIndex'] = 0; | |||
$tmpInfo['totalRows'] = 0; | |||
$tmpInfo['totalColumns'] = 0; | |||
if (isset($worksheet_ss['Name'])) { | |||
$tmpInfo['worksheetName'] = (string) $worksheet_ss['Name']; | |||
} else { | |||
$tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}"; | |||
} | |||
if (isset($worksheet->Table->Row)) { | |||
$rowIndex = 0; | |||
foreach ($worksheet->Table->Row as $rowData) { | |||
$columnIndex = 0; | |||
$rowHasData = false; | |||
foreach ($rowData->Cell as $cell) { | |||
if (isset($cell->Data)) { | |||
$tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); | |||
$rowHasData = true; | |||
} | |||
++$columnIndex; | |||
} | |||
++$rowIndex; | |||
if ($rowHasData) { | |||
$tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); | |||
} | |||
} | |||
} | |||
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); | |||
$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; | |||
$worksheetInfo[] = $tmpInfo; | |||
++$worksheetID; | |||
} | |||
return $worksheetInfo; | |||
} | |||
/** | |||
* Loads PHPExcel from file | |||
* | |||
* @param string $pFilename | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function load($pFilename) | |||
{ | |||
// Create new PHPExcel | |||
$objPHPExcel = new PHPExcel(); | |||
$objPHPExcel->removeSheetByIndex(0); | |||
// Load into this instance | |||
return $this->loadIntoExisting($pFilename, $objPHPExcel); | |||
} | |||
protected static function identifyFixedStyleValue($styleList, &$styleAttributeValue) | |||
{ | |||
$styleAttributeValue = strtolower($styleAttributeValue); | |||
foreach ($styleList as $style) { | |||
if ($styleAttributeValue == strtolower($style)) { | |||
$styleAttributeValue = $style; | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* pixel units to excel width units(units of 1/256th of a character width) | |||
* @param pxs | |||
* @return | |||
*/ | |||
protected static function pixel2WidthUnits($pxs) | |||
{ | |||
$UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); | |||
$widthUnits = 256 * ($pxs / 7); | |||
$widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; | |||
return $widthUnits; | |||
} | |||
/** | |||
* excel width units(units of 1/256th of a character width) to pixel units | |||
* @param widthUnits | |||
* @return | |||
*/ | |||
protected static function widthUnits2Pixel($widthUnits) | |||
{ | |||
$pixels = ($widthUnits / 256) * 7; | |||
$offsetWidthUnits = $widthUnits % 256; | |||
$pixels += round($offsetWidthUnits / (256 / 7)); | |||
return $pixels; | |||
} | |||
protected static function hex2str($hex) | |||
{ | |||
return chr(hexdec($hex[1])); | |||
} | |||
/** | |||
* Loads PHPExcel from file into PHPExcel instance | |||
* | |||
* @param string $pFilename | |||
* @param PHPExcel $objPHPExcel | |||
* @return PHPExcel | |||
* @throws PHPExcel_Reader_Exception | |||
*/ | |||
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) | |||
{ | |||
$fromFormats = array('\-', '\ '); | |||
$toFormats = array('-', ' '); | |||
$underlineStyles = array ( | |||
PHPExcel_Style_Font::UNDERLINE_NONE, | |||
PHPExcel_Style_Font::UNDERLINE_DOUBLE, | |||
PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, | |||
PHPExcel_Style_Font::UNDERLINE_SINGLE, | |||
PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING | |||
); | |||
$verticalAlignmentStyles = array ( | |||
PHPExcel_Style_Alignment::VERTICAL_BOTTOM, | |||
PHPExcel_Style_Alignment::VERTICAL_TOP, | |||
PHPExcel_Style_Alignment::VERTICAL_CENTER, | |||
PHPExcel_Style_Alignment::VERTICAL_JUSTIFY | |||
); | |||
$horizontalAlignmentStyles = array ( | |||
PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, | |||
PHPExcel_Style_Alignment::HORIZONTAL_LEFT, | |||
PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, | |||
PHPExcel_Style_Alignment::HORIZONTAL_CENTER, | |||
PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, | |||
PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY | |||
); | |||
$timezoneObj = new DateTimeZone('Europe/London'); | |||
$GMT = new DateTimeZone('UTC'); | |||
// Check if file exists | |||
if (!file_exists($pFilename)) { | |||
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); | |||
} | |||
if (!$this->canRead($pFilename)) { | |||
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); | |||
} | |||
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); | |||
$namespaces = $xml->getNamespaces(true); | |||
$docProps = $objPHPExcel->getProperties(); | |||
if (isset($xml->DocumentProperties[0])) { | |||
foreach ($xml->DocumentProperties[0] as $propertyName => $propertyValue) { | |||
switch ($propertyName) { | |||
case 'Title': | |||
$docProps->setTitle(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Subject': | |||
$docProps->setSubject(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Author': | |||
$docProps->setCreator(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Created': | |||
$creationDate = strtotime($propertyValue); | |||
$docProps->setCreated($creationDate); | |||
break; | |||
case 'LastAuthor': | |||
$docProps->setLastModifiedBy(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'LastSaved': | |||
$lastSaveDate = strtotime($propertyValue); | |||
$docProps->setModified($lastSaveDate); | |||
break; | |||
case 'Company': | |||
$docProps->setCompany(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Category': | |||
$docProps->setCategory(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Manager': | |||
$docProps->setManager(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Keywords': | |||
$docProps->setKeywords(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
case 'Description': | |||
$docProps->setDescription(self::convertStringEncoding($propertyValue, $this->charSet)); | |||
break; | |||
} | |||
} | |||
} | |||
if (isset($xml->CustomDocumentProperties)) { | |||
foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { | |||
$propertyAttributes = $propertyValue->attributes($namespaces['dt']); | |||
$propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/', 'PHPExcel_Reader_Excel2003XML::hex2str', $propertyName); | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_UNKNOWN; | |||
switch ((string) $propertyAttributes) { | |||
case 'string': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; | |||
$propertyValue = trim($propertyValue); | |||
break; | |||
case 'boolean': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; | |||
$propertyValue = (bool) $propertyValue; | |||
break; | |||
case 'integer': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_INTEGER; | |||
$propertyValue = intval($propertyValue); | |||
break; | |||
case 'float': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; | |||
$propertyValue = floatval($propertyValue); | |||
break; | |||
case 'dateTime.tz': | |||
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; | |||
$propertyValue = strtotime(trim($propertyValue)); | |||
break; | |||
} | |||
$docProps->setCustomProperty($propertyName, $propertyValue, $propertyType); | |||
} | |||
} | |||
foreach ($xml->Styles[0] as $style) { | |||
$style_ss = $style->attributes($namespaces['ss']); | |||
$styleID = (string) $style_ss['ID']; | |||
// echo 'Style ID = '.$styleID.'<br />'; | |||
$this->styles[$styleID] = (isset($this->styles['Default'])) ? $this->styles['Default'] : array(); | |||
foreach ($style as $styleType => $styleData) { | |||
$styleAttributes = $styleData->attributes($namespaces['ss']); | |||
// echo $styleType.'<br />'; | |||
switch ($styleType) { | |||
case 'Alignment': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
$styleAttributeValue = (string) $styleAttributeValue; | |||
switch ($styleAttributeKey) { | |||
case 'Vertical': | |||
if (self::identifyFixedStyleValue($verticalAlignmentStyles, $styleAttributeValue)) { | |||
$this->styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; | |||
} | |||
break; | |||
case 'Horizontal': | |||
if (self::identifyFixedStyleValue($horizontalAlignmentStyles, $styleAttributeValue)) { | |||
$this->styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; | |||
} | |||
break; | |||
case 'WrapText': | |||
$this->styles[$styleID]['alignment']['wrap'] = true; | |||
break; | |||
} | |||
} | |||
break; | |||
case 'Borders': | |||
foreach ($styleData->Border as $borderStyle) { | |||
$borderAttributes = $borderStyle->attributes($namespaces['ss']); | |||
$thisBorder = array(); | |||
foreach ($borderAttributes as $borderStyleKey => $borderStyleValue) { | |||
// echo $borderStyleKey.' = '.$borderStyleValue.'<br />'; | |||
switch ($borderStyleKey) { | |||
case 'LineStyle': | |||
$thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; | |||
// $thisBorder['style'] = $borderStyleValue; | |||
break; | |||
case 'Weight': | |||
// $thisBorder['style'] = $borderStyleValue; | |||
break; | |||
case 'Position': | |||
$borderPosition = strtolower($borderStyleValue); | |||
break; | |||
case 'Color': | |||
$borderColour = substr($borderStyleValue, 1); | |||
$thisBorder['color']['rgb'] = $borderColour; | |||
break; | |||
} | |||
} | |||
if (!empty($thisBorder)) { | |||
if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { | |||
$this->styles[$styleID]['borders'][$borderPosition] = $thisBorder; | |||
} | |||
} | |||
} | |||
break; | |||
case 'Font': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
$styleAttributeValue = (string) $styleAttributeValue; | |||
switch ($styleAttributeKey) { | |||
case 'FontName': | |||
$this->styles[$styleID]['font']['name'] = $styleAttributeValue; | |||
break; | |||
case 'Size': | |||
$this->styles[$styleID]['font']['size'] = $styleAttributeValue; | |||
break; | |||
case 'Color': | |||
$this->styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue, 1); | |||
break; | |||
case 'Bold': | |||
$this->styles[$styleID]['font']['bold'] = true; | |||
break; | |||
case 'Italic': | |||
$this->styles[$styleID]['font']['italic'] = true; | |||
break; | |||
case 'Underline': | |||
if (self::identifyFixedStyleValue($underlineStyles, $styleAttributeValue)) { | |||
$this->styles[$styleID]['font']['underline'] = $styleAttributeValue; | |||
} | |||
break; | |||
} | |||
} | |||
break; | |||
case 'Interior': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
switch ($styleAttributeKey) { | |||
case 'Color': | |||
$this->styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue, 1); | |||
break; | |||
} | |||
} | |||
break; | |||
case 'NumberFormat': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
$styleAttributeValue = str_replace($fromFormats, $toFormats, $styleAttributeValue); | |||
switch ($styleAttributeValue) { | |||
case 'Short Date': | |||
$styleAttributeValue = 'dd/mm/yyyy'; | |||
break; | |||
} | |||
if ($styleAttributeValue > '') { | |||
$this->styles[$styleID]['numberformat']['code'] = $styleAttributeValue; | |||
} | |||
} | |||
break; | |||
case 'Protection': | |||
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) { | |||
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />'; | |||
} | |||
break; | |||
} | |||
} | |||
// print_r($this->styles[$styleID]); | |||
// echo '<hr />'; | |||
} | |||
// echo '<hr />'; | |||
$worksheetID = 0; | |||
$xml_ss = $xml->children($namespaces['ss']); | |||
foreach ($xml_ss->Worksheet as $worksheet) { | |||
$worksheet_ss = $worksheet->attributes($namespaces['ss']); | |||
if ((isset($this->loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && | |||
(!in_array($worksheet_ss['Name'], $this->loadSheetsOnly))) { | |||
continue; | |||
} | |||
// echo '<h3>Worksheet: ', $worksheet_ss['Name'],'<h3>'; | |||
// | |||
// Create new Worksheet | |||
$objPHPExcel->createSheet(); | |||
$objPHPExcel->setActiveSheetIndex($worksheetID); | |||
if (isset($worksheet_ss['Name'])) { | |||
$worksheetName = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet); | |||
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in | |||
// formula cells... during the load, all formulae should be correct, and we're simply bringing | |||
// the worksheet name in line with the formula, not the reverse | |||
$objPHPExcel->getActiveSheet()->setTitle($worksheetName, false); | |||
} | |||
$columnID = 'A'; | |||
if (isset($worksheet->Table->Column)) { | |||
foreach ($worksheet->Table->Column as $columnData) { | |||
$columnData_ss = $columnData->attributes($namespaces['ss']); | |||
if (isset($columnData_ss['Index'])) { | |||
$columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); | |||
} | |||
if (isset($columnData_ss['Width'])) { | |||
$columnWidth = $columnData_ss['Width']; | |||
// echo '<b>Setting column width for '.$columnID.' to '.$columnWidth.'</b><br />'; | |||
$objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); | |||
} | |||
++$columnID; | |||
} | |||
} | |||
$rowID = 1; | |||
if (isset($worksheet->Table->Row)) { | |||
$additionalMergedCells = 0; | |||
foreach ($worksheet->Table->Row as $rowData) { | |||
$rowHasData = false; | |||
$row_ss = $rowData->attributes($namespaces['ss']); | |||
if (isset($row_ss['Index'])) { | |||
$rowID = (integer) $row_ss['Index']; | |||
} | |||
// echo '<b>Row '.$rowID.'</b><br />'; | |||
$columnID = 'A'; | |||
foreach ($rowData->Cell as $cell) { | |||
$cell_ss = $cell->attributes($namespaces['ss']); | |||
if (isset($cell_ss['Index'])) { | |||
$columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); | |||
} | |||
$cellRange = $columnID.$rowID; | |||
if ($this->getReadFilter() !== null) { | |||
if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { | |||
continue; | |||
} | |||
} | |||
if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { | |||
$columnTo = $columnID; | |||
if (isset($cell_ss['MergeAcross'])) { | |||
$additionalMergedCells += (int)$cell_ss['MergeAcross']; | |||
$columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); | |||
} | |||
$rowTo = $rowID; | |||
if (isset($cell_ss['MergeDown'])) { | |||
$rowTo = $rowTo + $cell_ss['MergeDown']; | |||
} | |||
$cellRange .= ':'.$columnTo.$rowTo; | |||
$objPHPExcel->getActiveSheet()->mergeCells($cellRange); | |||
} | |||
$cellIsSet = $hasCalculatedValue = false; | |||
$cellDataFormula = ''; | |||
if (isset($cell_ss['Formula'])) { | |||
$cellDataFormula = $cell_ss['Formula']; | |||
// added this as a check for array formulas | |||
if (isset($cell_ss['ArrayRange'])) { | |||
$cellDataCSEFormula = $cell_ss['ArrayRange']; | |||
// echo "found an array formula at ".$columnID.$rowID."<br />"; | |||
} | |||
$hasCalculatedValue = true; | |||
} | |||
if (isset($cell->Data)) { | |||
$cellValue = $cellData = $cell->Data; | |||
$type = PHPExcel_Cell_DataType::TYPE_NULL; | |||
$cellData_ss = $cellData->attributes($namespaces['ss']); | |||
if (isset($cellData_ss['Type'])) { | |||
$cellDataType = $cellData_ss['Type']; | |||
switch ($cellDataType) { | |||
/* | |||
const TYPE_STRING = 's'; | |||
const TYPE_FORMULA = 'f'; | |||
const TYPE_NUMERIC = 'n'; | |||
const TYPE_BOOL = 'b'; | |||
const TYPE_NULL = 'null'; | |||
const TYPE_INLINE = 'inlineStr'; | |||
const TYPE_ERROR = 'e'; | |||
*/ | |||
case 'String': | |||
$cellValue = self::convertStringEncoding($cellValue, $this->charSet); | |||
$type = PHPExcel_Cell_DataType::TYPE_STRING; | |||
break; | |||
case 'Number': | |||
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
$cellValue = (float) $cellValue; | |||
if (floor($cellValue) == $cellValue) { | |||
$cellValue = (integer) $cellValue; | |||
} | |||
break; | |||
case 'Boolean': | |||
$type = PHPExcel_Cell_DataType::TYPE_BOOL; | |||
$cellValue = ($cellValue != 0); | |||
break; | |||
case 'DateTime': | |||
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC; | |||
$cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); | |||
break; | |||
case 'Error': | |||
$type = PHPExcel_Cell_DataType::TYPE_ERROR; | |||
break; | |||
} | |||
} | |||
if ($hasCalculatedValue) { | |||
// echo 'FORMULA<br />'; | |||
$type = PHPExcel_Cell_DataType::TYPE_FORMULA; | |||
$columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); | |||
if (substr($cellDataFormula, 0, 3) == 'of:') { | |||
$cellDataFormula = substr($cellDataFormula, 3); | |||
// echo 'Before: ', $cellDataFormula,'<br />'; | |||
$temp = explode('"', $cellDataFormula); | |||
$key = false; | |||
foreach ($temp as &$value) { | |||
// Only replace in alternate array entries (i.e. non-quoted blocks) | |||
if ($key = !$key) { | |||
$value = str_replace(array('[.', '.', ']'), '', $value); | |||
} | |||
} | |||
} else { | |||
// Convert R1C1 style references to A1 style references (but only when not quoted) | |||
// echo 'Before: ', $cellDataFormula,'<br />'; | |||
$temp = explode('"', $cellDataFormula); | |||
$key = false; | |||
foreach ($temp as &$value) { | |||
// Only replace in alternate array entries (i.e. non-quoted blocks) | |||
if ($key = !$key) { | |||
preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/', $value, $cellReferences, PREG_SET_ORDER + PREG_OFFSET_CAPTURE); | |||
// Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way | |||
// through the formula from left to right. Reversing means that we work right to left.through | |||
// the formula | |||
$cellReferences = array_reverse($cellReferences); | |||
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, | |||
// then modify the formula to use that new reference | |||
foreach ($cellReferences as $cellReference) { | |||
$rowReference = $cellReference[2][0]; | |||
// Empty R reference is the current row | |||
if ($rowReference == '') { | |||
$rowReference = $rowID; | |||
} | |||
// Bracketed R references are relative to the current row | |||
if ($rowReference{0} == '[') { | |||
$rowReference = $rowID + trim($rowReference, '[]'); | |||
} | |||
$columnReference = $cellReference[4][0]; | |||
// Empty C reference is the current column | |||
if ($columnReference == '') { | |||
$columnReference = $columnNumber; | |||
} | |||
// Bracketed C references are relative to the current column | |||
if ($columnReference{0} == '[') { | |||
$columnReference = $columnNumber + trim($columnReference, '[]'); | |||
} | |||
$A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; | |||
$value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0])); | |||
} | |||
} | |||
} | |||
} | |||
unset($value); | |||
// Then rebuild the formula string | |||
$cellDataFormula = implode('"', $temp); | |||
// echo 'After: ', $cellDataFormula,'<br />'; | |||
} | |||
// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'<br />'; | |||
// | |||
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue), $type); | |||
if ($hasCalculatedValue) { | |||
// echo 'Formula result is '.$cellValue.'<br />'; | |||
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); | |||
} | |||
$cellIsSet = $rowHasData = true; | |||
} | |||
if (isset($cell->Comment)) { | |||
// echo '<b>comment found</b><br />'; | |||
$commentAttributes = $cell->Comment->attributes($namespaces['ss']); | |||
$author = 'unknown'; | |||
if (isset($commentAttributes->Author)) { | |||
$author = (string)$commentAttributes->Author; | |||
// echo 'Author: ', $author,'<br />'; | |||
} | |||
$node = $cell->Comment->Data->asXML(); | |||
// $annotation = str_replace('html:','',substr($node,49,-10)); | |||
// echo $annotation,'<br />'; | |||
$annotation = strip_tags($node); | |||
// echo 'Annotation: ', $annotation,'<br />'; | |||
$objPHPExcel->getActiveSheet()->getComment($columnID.$rowID)->setAuthor(self::convertStringEncoding($author, $this->charSet))->setText($this->parseRichText($annotation)); | |||
} | |||
if (($cellIsSet) && (isset($cell_ss['StyleID']))) { | |||
$style = (string) $cell_ss['StyleID']; | |||
// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'<br />'; | |||
if ((isset($this->styles[$style])) && (!empty($this->styles[$style]))) { | |||
// echo 'Cell '.$columnID.$rowID.'<br />'; | |||
// print_r($this->styles[$style]); | |||
// echo '<br />'; | |||
if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { | |||
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(null); | |||
} | |||
$objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->styles[$style]); | |||
} | |||
} | |||
++$columnID; | |||
while ($additionalMergedCells > 0) { | |||
++$columnID; | |||
$additionalMergedCells--; | |||
} | |||
} | |||
if ($rowHasData) { | |||
if (isset($row_ss['StyleID'])) { | |||
$rowStyle = $row_ss['StyleID']; | |||
} | |||
if (isset($row_ss['Height'])) { | |||
$rowHeight = $row_ss['Height']; | |||
// echo '<b>Setting row height to '.$rowHeight.'</b><br />'; | |||
$objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); | |||
} | |||
} | |||
++$rowID; | |||
} | |||
} | |||
++$worksheetID; | |||
} | |||
// Return | |||
return $objPHPExcel; | |||
} | |||
protected static function convertStringEncoding($string, $charset) | |||
{ | |||
if ($charset != 'UTF-8') { | |||
return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', $charset); | |||
} | |||
return $string; | |||
} | |||
protected function parseRichText($is = '') | |||
{ | |||
$value = new PHPExcel_RichText(); | |||
$value->createText(self::convertStringEncoding($is, $this->charSet)); | |||
return $value; | |||
} | |||
} |
@ -0,0 +1,520 @@ | |||
<?php | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader_Excel2007 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
/** | |||
* PHPExcel_Reader_Excel2007_Chart | |||
* | |||
* @category PHPExcel | |||
* @package PHPExcel_Reader_Excel2007 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
*/ | |||
class PHPExcel_Reader_Excel2007_Chart | |||
{ | |||
private static function getAttribute($component, $name, $format) | |||
{ | |||
$attributes = $component->attributes(); | |||
if (isset($attributes[$name])) { | |||
if ($format == 'string') { | |||
return (string) $attributes[$name]; | |||
} elseif ($format == 'integer') { | |||
return (integer) $attributes[$name]; | |||
} elseif ($format == 'boolean') { | |||
return (boolean) ($attributes[$name] === '0' || $attributes[$name] !== 'true') ? false : true; | |||
} else { | |||
return (float) $attributes[$name]; | |||
} | |||
} | |||
return null; | |||
} | |||
private static function readColor($color, $background = false) | |||
{ | |||
if (isset($color["rgb"])) { | |||
return (string)$color["rgb"]; | |||
} elseif (isset($color["indexed"])) { | |||
return PHPExcel_Style_Color::indexedColor($color["indexed"]-7, $background)->getARGB(); | |||
} | |||
} | |||
public static function readChart($chartElements, $chartName) | |||
{ | |||
$namespacesChartMeta = $chartElements->getNamespaces(true); | |||
$chartElementsC = $chartElements->children($namespacesChartMeta['c']); | |||
$XaxisLabel = $YaxisLabel = $legend = $title = null; | |||
$dispBlanksAs = $plotVisOnly = null; | |||
foreach ($chartElementsC as $chartElementKey => $chartElement) { | |||
switch ($chartElementKey) { | |||
case "chart": | |||
foreach ($chartElement as $chartDetailsKey => $chartDetails) { | |||
$chartDetailsC = $chartDetails->children($namespacesChartMeta['c']); | |||
switch ($chartDetailsKey) { | |||
case "plotArea": | |||
$plotAreaLayout = $XaxisLable = $YaxisLable = null; | |||
$plotSeries = $plotAttributes = array(); | |||
foreach ($chartDetails as $chartDetailKey => $chartDetail) { | |||
switch ($chartDetailKey) { | |||
case "layout": | |||
$plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta, 'plotArea'); | |||
break; | |||
case "catAx": | |||
if (isset($chartDetail->title)) { | |||
$XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta, 'cat'); | |||
} | |||
break; | |||
case "dateAx": | |||
if (isset($chartDetail->title)) { | |||
$XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta, 'cat'); | |||
} | |||
break; | |||
case "valAx": | |||
if (isset($chartDetail->title)) { | |||
$YaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta, 'cat'); | |||
} | |||
break; | |||
case "barChart": | |||
case "bar3DChart": | |||
$barDirection = self::getAttribute($chartDetail->barDir, 'val', 'string'); | |||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotSer->setPlotDirection($barDirection); | |||
$plotSeries[] = $plotSer; | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "lineChart": | |||
case "line3DChart": | |||
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "areaChart": | |||
case "area3DChart": | |||
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "doughnutChart": | |||
case "pieChart": | |||
case "pie3DChart": | |||
$explosion = isset($chartDetail->ser->explosion); | |||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotSer->setPlotStyle($explosion); | |||
$plotSeries[] = $plotSer; | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "scatterChart": | |||
$scatterStyle = self::getAttribute($chartDetail->scatterStyle, 'val', 'string'); | |||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotSer->setPlotStyle($scatterStyle); | |||
$plotSeries[] = $plotSer; | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "bubbleChart": | |||
$bubbleScale = self::getAttribute($chartDetail->bubbleScale, 'val', 'integer'); | |||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotSer->setPlotStyle($bubbleScale); | |||
$plotSeries[] = $plotSer; | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "radarChart": | |||
$radarStyle = self::getAttribute($chartDetail->radarStyle, 'val', 'string'); | |||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotSer->setPlotStyle($radarStyle); | |||
$plotSeries[] = $plotSer; | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "surfaceChart": | |||
case "surface3DChart": | |||
$wireFrame = self::getAttribute($chartDetail->wireframe, 'val', 'boolean'); | |||
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotSer->setPlotStyle($wireFrame); | |||
$plotSeries[] = $plotSer; | |||
$plotAttributes = self::readChartAttributes($chartDetail); | |||
break; | |||
case "stockChart": | |||
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); | |||
$plotAttributes = self::readChartAttributes($plotAreaLayout); | |||
break; | |||
} | |||
} | |||
if ($plotAreaLayout == null) { | |||
$plotAreaLayout = new PHPExcel_Chart_Layout(); | |||
} | |||
$plotArea = new PHPExcel_Chart_PlotArea($plotAreaLayout, $plotSeries); | |||
self::setChartAttributes($plotAreaLayout, $plotAttributes); | |||
break; | |||
case "plotVisOnly": | |||
$plotVisOnly = self::getAttribute($chartDetails, 'val', 'string'); | |||
break; | |||
case "dispBlanksAs": | |||
$dispBlanksAs = self::getAttribute($chartDetails, 'val', 'string'); | |||
break; | |||
case "title": | |||
$title = self::chartTitle($chartDetails, $namespacesChartMeta, 'title'); | |||
break; | |||
case "legend": | |||
$legendPos = 'r'; | |||
$legendLayout = null; | |||
$legendOverlay = false; | |||
foreach ($chartDetails as $chartDetailKey => $chartDetail) { | |||
switch ($chartDetailKey) { | |||
case "legendPos": | |||
$legendPos = self::getAttribute($chartDetail, 'val', 'string'); | |||
break; | |||
case "overlay": | |||
$legendOverlay = self::getAttribute($chartDetail, 'val', 'boolean'); | |||
break; | |||
case "layout": | |||
$legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta, 'legend'); | |||
break; | |||
} | |||
} | |||
$legend = new PHPExcel_Chart_Legend($legendPos, $legendLayout, $legendOverlay); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
$chart = new PHPExcel_Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, $dispBlanksAs, $XaxisLabel, $YaxisLabel); | |||
return $chart; | |||
} | |||
private static function chartTitle($titleDetails, $namespacesChartMeta, $type) | |||
{ | |||
$caption = array(); | |||
$titleLayout = null; | |||
foreach ($titleDetails as $titleDetailKey => $chartDetail) { | |||
switch ($titleDetailKey) { | |||
case "tx": | |||
$titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']); | |||
foreach ($titleDetails as $titleKey => $titleDetail) { | |||
switch ($titleKey) { | |||
case "p": | |||
$titleDetailPart = $titleDetail->children($namespacesChartMeta['a']); | |||
$caption[] = self::parseRichText($titleDetailPart); | |||
} | |||
} | |||
break; | |||
case "layout": | |||
$titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); | |||
break; | |||
} | |||
} | |||
return new PHPExcel_Chart_Title($caption, $titleLayout); | |||
} | |||
private static function chartLayoutDetails($chartDetail, $namespacesChartMeta) | |||
{ | |||
if (!isset($chartDetail->manualLayout)) { | |||
return null; | |||
} | |||
$details = $chartDetail->manualLayout->children($namespacesChartMeta['c']); | |||
if (is_null($details)) { | |||
return null; | |||
} | |||
$layout = array(); | |||
foreach ($details as $detailKey => $detail) { | |||
// echo $detailKey, ' => ',self::getAttribute($detail, 'val', 'string'),PHP_EOL; | |||
$layout[$detailKey] = self::getAttribute($detail, 'val', 'string'); | |||
} | |||
return new PHPExcel_Chart_Layout($layout); | |||
} | |||
private static function chartDataSeries($chartDetail, $namespacesChartMeta, $plotType) | |||
{ | |||
$multiSeriesType = null; | |||
$smoothLine = false; | |||
$seriesLabel = $seriesCategory = $seriesValues = $plotOrder = array(); | |||
$seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']); | |||
foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) { | |||
switch ($seriesDetailKey) { | |||
case "grouping": | |||
$multiSeriesType = self::getAttribute($chartDetail->grouping, 'val', 'string'); | |||
break; | |||
case "ser": | |||
$marker = null; | |||
foreach ($seriesDetails as $seriesKey => $seriesDetail) { | |||
switch ($seriesKey) { | |||
case "idx": | |||
$seriesIndex = self::getAttribute($seriesDetail, 'val', 'integer'); | |||
break; | |||
case "order": | |||
$seriesOrder = self::getAttribute($seriesDetail, 'val', 'integer'); | |||
$plotOrder[$seriesIndex] = $seriesOrder; | |||
break; | |||
case "tx": | |||
$seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta); | |||
break; | |||
case "marker": | |||
$marker = self::getAttribute($seriesDetail->symbol, 'val', 'string'); | |||
break; | |||
case "smooth": | |||
$smoothLine = self::getAttribute($seriesDetail, 'val', 'boolean'); | |||
break; | |||
case "cat": | |||
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta); | |||
break; | |||
case "val": | |||
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker); | |||
break; | |||
case "xVal": | |||
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker); | |||
break; | |||
case "yVal": | |||
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
return new PHPExcel_Chart_DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine); | |||
} | |||
private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null, $smoothLine = false) | |||
{ | |||
if (isset($seriesDetail->strRef)) { | |||
$seriesSource = (string) $seriesDetail->strRef->f; | |||
$seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's'); | |||
return new PHPExcel_Chart_DataSeriesValues('String', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine); | |||
} elseif (isset($seriesDetail->numRef)) { | |||
$seriesSource = (string) $seriesDetail->numRef->f; | |||
$seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c'])); | |||
return new PHPExcel_Chart_DataSeriesValues('Number', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine); | |||
} elseif (isset($seriesDetail->multiLvlStrRef)) { | |||
$seriesSource = (string) $seriesDetail->multiLvlStrRef->f; | |||
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's'); | |||
$seriesData['pointCount'] = count($seriesData['dataValues']); | |||
return new PHPExcel_Chart_DataSeriesValues('String', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine); | |||
} elseif (isset($seriesDetail->multiLvlNumRef)) { | |||
$seriesSource = (string) $seriesDetail->multiLvlNumRef->f; | |||
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's'); | |||
$seriesData['pointCount'] = count($seriesData['dataValues']); | |||
return new PHPExcel_Chart_DataSeriesValues('String', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine); | |||
} | |||
return null; | |||
} | |||
private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n') | |||
{ | |||
$seriesVal = array(); | |||
$formatCode = ''; | |||
$pointCount = 0; | |||
foreach ($seriesValueSet as $seriesValueIdx => $seriesValue) { | |||
switch ($seriesValueIdx) { | |||
case 'ptCount': | |||
$pointCount = self::getAttribute($seriesValue, 'val', 'integer'); | |||
break; | |||
case 'formatCode': | |||
$formatCode = (string) $seriesValue; | |||
break; | |||
case 'pt': | |||
$pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); | |||
if ($dataType == 's') { | |||
$seriesVal[$pointVal] = (string) $seriesValue->v; | |||
} else { | |||
$seriesVal[$pointVal] = (float) $seriesValue->v; | |||
} | |||
break; | |||
} | |||
} | |||
return array( | |||
'formatCode' => $formatCode, | |||
'pointCount' => $pointCount, | |||
'dataValues' => $seriesVal | |||
); | |||
} | |||
private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n') | |||
{ | |||
$seriesVal = array(); | |||
$formatCode = ''; | |||
$pointCount = 0; | |||
foreach ($seriesValueSet->lvl as $seriesLevelIdx => $seriesLevel) { | |||
foreach ($seriesLevel as $seriesValueIdx => $seriesValue) { | |||
switch ($seriesValueIdx) { | |||
case 'ptCount': | |||
$pointCount = self::getAttribute($seriesValue, 'val', 'integer'); | |||
break; | |||
case 'formatCode': | |||
$formatCode = (string) $seriesValue; | |||
break; | |||
case 'pt': | |||
$pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); | |||
if ($dataType == 's') { | |||
$seriesVal[$pointVal][] = (string) $seriesValue->v; | |||
} else { | |||
$seriesVal[$pointVal][] = (float) $seriesValue->v; | |||
} | |||
break; | |||
} | |||
} | |||
} | |||
return array( | |||
'formatCode' => $formatCode, | |||
'pointCount' => $pointCount, | |||
'dataValues' => $seriesVal | |||
); | |||
} | |||
private static function parseRichText($titleDetailPart = null) | |||
{ | |||
$value = new PHPExcel_RichText(); | |||
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) { | |||
if (isset($titleDetailElement->t)) { | |||
$objText = $value->createTextRun((string) $titleDetailElement->t); | |||
} | |||
if (isset($titleDetailElement->rPr)) { | |||
if (isset($titleDetailElement->rPr->rFont["val"])) { | |||
$objText->getFont()->setName((string) $titleDetailElement->rPr->rFont["val"]); | |||
} | |||
$fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer')); | |||
if (!is_null($fontSize)) { | |||
$objText->getFont()->setSize(floor($fontSize / 100)); | |||
} | |||
$fontColor = (self::getAttribute($titleDetailElement->rPr, 'color', 'string')); | |||
if (!is_null($fontColor)) { | |||
$objText->getFont()->setColor(new PHPExcel_Style_Color(self::readColor($fontColor))); | |||
} | |||
$bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean'); | |||
if (!is_null($bold)) { | |||
$objText->getFont()->setBold($bold); | |||
} | |||
$italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean'); | |||
if (!is_null($italic)) { | |||
$objText->getFont()->setItalic($italic); | |||
} | |||
$baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer'); | |||
if (!is_null($baseline)) { | |||
if ($baseline > 0) { | |||
$objText->getFont()->setSuperScript(true); | |||
} elseif ($baseline < 0) { | |||
$objText->getFont()->setSubScript(true); | |||
} | |||
} | |||
$underscore = (self::getAttribute($titleDetailElement->rPr, 'u', 'string')); | |||
if (!is_null($underscore)) { | |||
if ($underscore == 'sng') { | |||
$objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); | |||
} elseif ($underscore == 'dbl') { | |||
$objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE); | |||
} else { | |||
$objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_NONE); | |||
} | |||
} | |||
$strikethrough = (self::getAttribute($titleDetailElement->rPr, 's', 'string')); | |||
if (!is_null($strikethrough)) { | |||
if ($strikethrough == 'noStrike') { | |||
$objText->getFont()->setStrikethrough(false); | |||
} else { | |||
$objText->getFont()->setStrikethrough(true); | |||
} | |||
} | |||
} | |||
} | |||
return $value; | |||
} | |||
private static function readChartAttributes($chartDetail) | |||
{ | |||
$plotAttributes = array(); | |||
if (isset($chartDetail->dLbls)) { | |||
if (isset($chartDetail->dLbls->howLegendKey)) { | |||
$plotAttributes['showLegendKey'] = self::getAttribute($chartDetail->dLbls->showLegendKey, 'val', 'string'); | |||
} | |||
if (isset($chartDetail->dLbls->showVal)) { | |||
$plotAttributes['showVal'] = self::getAttribute($chartDetail->dLbls->showVal, 'val', 'string'); | |||
} | |||
if (isset($chartDetail->dLbls->showCatName)) { | |||
$plotAttributes['showCatName'] = self::getAttribute($chartDetail->dLbls->showCatName, 'val', 'string'); | |||
} | |||
if (isset($chartDetail->dLbls->showSerName)) { | |||
$plotAttributes['showSerName'] = self::getAttribute($chartDetail->dLbls->showSerName, 'val', 'string'); | |||
} | |||
if (isset($chartDetail->dLbls->showPercent)) { | |||
$plotAttributes['showPercent'] = self::getAttribute($chartDetail->dLbls->showPercent, 'val', 'string'); | |||
} | |||
if (isset($chartDetail->dLbls->showBubbleSize)) { | |||
$plotAttributes['showBubbleSize'] = self::getAttribute($chartDetail->dLbls->showBubbleSize, 'val', 'string'); | |||
} | |||
if (isset($chartDetail->dLbls->showLeaderLines)) { | |||
$plotAttributes['showLeaderLines'] = self::getAttribute($chartDetail->dLbls->showLeaderLines, 'val', 'string'); | |||
} | |||
} | |||
return $plotAttributes; | |||
} | |||
private static function setChartAttributes($plotArea, $plotAttributes) | |||
{ | |||
foreach ($plotAttributes as $plotAttributeKey => $plotAttributeValue) { | |||
switch ($plotAttributeKey) { | |||
case 'showLegendKey': | |||
$plotArea->setShowLegendKey($plotAttributeValue); | |||
break; | |||
case 'showVal': | |||
$plotArea->setShowVal($plotAttributeValue); | |||
break; | |||
case 'showCatName': | |||
$plotArea->setShowCatName($plotAttributeValue); | |||
break; | |||
case 'showSerName': | |||
$plotArea->setShowSerName($plotAttributeValue); | |||
break; | |||
case 'showPercent': | |||
$plotArea->setShowPercent($plotAttributeValue); | |||
break; | |||
case 'showBubbleSize': | |||
$plotArea->setShowBubbleSize($plotAttributeValue); | |||
break; | |||
case 'showLeaderLines': | |||
$plotArea->setShowLeaderLines($plotAttributeValue); | |||
break; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,127 @@ | |||
<?php | |||
/** | |||
* PHPExcel | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader_Excel2007 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
/** | |||
* PHPExcel_Reader_Excel2007_Theme | |||
* | |||
* @category PHPExcel | |||
* @package PHPExcel_Reader_Excel2007 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
*/ | |||
class PHPExcel_Reader_Excel2007_Theme | |||
{ | |||
/** | |||
* Theme Name | |||
* | |||
* @var string | |||
*/ | |||
private $themeName; | |||
/** | |||
* Colour Scheme Name | |||
* | |||
* @var string | |||
*/ | |||
private $colourSchemeName; | |||
/** | |||
* Colour Map indexed by position | |||
* | |||
* @var array of string | |||
*/ | |||
private $colourMapValues; | |||
/** | |||
* Colour Map | |||
* | |||
* @var array of string | |||
*/ | |||
private $colourMap; | |||
/** | |||
* Create a new PHPExcel_Theme | |||
* | |||
*/ | |||
public function __construct($themeName, $colourSchemeName, $colourMap) | |||
{ | |||
// Initialise values | |||
$this->themeName = $themeName; | |||
$this->colourSchemeName = $colourSchemeName; | |||
$this->colourMap = $colourMap; | |||
} | |||
/** | |||
* Get Theme Name | |||
* | |||
* @return string | |||
*/ | |||
public function getThemeName() | |||
{ | |||
return $this->themeName; | |||
} | |||
/** | |||
* Get colour Scheme Name | |||
* | |||
* @return string | |||
*/ | |||
public function getColourSchemeName() | |||
{ | |||
return $this->colourSchemeName; | |||
} | |||
/** | |||
* Get colour Map Value by Position | |||
* | |||
* @return string | |||
*/ | |||
public function getColourByIndex($index = 0) | |||
{ | |||
if (isset($this->colourMap[$index])) { | |||
return $this->colourMap[$index]; | |||
} | |||
return null; | |||
} | |||
/** | |||
* Implement PHP __clone to create a deep clone, not just a shallow copy. | |||
*/ | |||
public function __clone() | |||
{ | |||
$vars = get_object_vars($this); | |||
foreach ($vars as $key => $value) { | |||
if ((is_object($value)) && ($key != '_parent')) { | |||
$this->$key = clone $value; | |||
} else { | |||
$this->$key = $value; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,32 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_Color | |||
{ | |||
/** | |||
* Read color | |||
* | |||
* @param int $color Indexed color | |||
* @param array $palette Color palette | |||
* @return array RGB color value, example: array('rgb' => 'FF0000') | |||
*/ | |||
public static function map($color, $palette, $version) | |||
{ | |||
if ($color <= 0x07 || $color >= 0x40) { | |||
// special built-in color | |||
return PHPExcel_Reader_Excel5_Color_BuiltIn::lookup($color); | |||
} elseif (isset($palette) && isset($palette[$color - 8])) { | |||
// palette color, color index 0x08 maps to pallete index 0 | |||
return $palette[$color - 8]; | |||
} else { | |||
// default color table | |||
if ($version == PHPExcel_Reader_Excel5::XLS_BIFF8) { | |||
return PHPExcel_Reader_Excel5_Color_BIFF8::lookup($color); | |||
} else { | |||
// BIFF5 | |||
return PHPExcel_Reader_Excel5_Color_BIFF5::lookup($color); | |||
} | |||
} | |||
return $color; | |||
} | |||
} |
@ -0,0 +1,77 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_Color_BIFF5 | |||
{ | |||
protected static $map = array( | |||
0x08 => '000000', | |||
0x09 => 'FFFFFF', | |||
0x0A => 'FF0000', | |||
0x0B => '00FF00', | |||
0x0C => '0000FF', | |||
0x0D => 'FFFF00', | |||
0x0E => 'FF00FF', | |||
0x0F => '00FFFF', | |||
0x10 => '800000', | |||
0x11 => '008000', | |||
0x12 => '000080', | |||
0x13 => '808000', | |||
0x14 => '800080', | |||
0x15 => '008080', | |||
0x16 => 'C0C0C0', | |||
0x17 => '808080', | |||
0x18 => '8080FF', | |||
0x19 => '802060', | |||
0x1A => 'FFFFC0', | |||
0x1B => 'A0E0F0', | |||
0x1C => '600080', | |||
0x1D => 'FF8080', | |||
0x1E => '0080C0', | |||
0x1F => 'C0C0FF', | |||
0x20 => '000080', | |||
0x21 => 'FF00FF', | |||
0x22 => 'FFFF00', | |||
0x23 => '00FFFF', | |||
0x24 => '800080', | |||
0x25 => '800000', | |||
0x26 => '008080', | |||
0x27 => '0000FF', | |||
0x28 => '00CFFF', | |||
0x29 => '69FFFF', | |||
0x2A => 'E0FFE0', | |||
0x2B => 'FFFF80', | |||
0x2C => 'A6CAF0', | |||
0x2D => 'DD9CB3', | |||
0x2E => 'B38FEE', | |||
0x2F => 'E3E3E3', | |||
0x30 => '2A6FF9', | |||
0x31 => '3FB8CD', | |||
0x32 => '488436', | |||
0x33 => '958C41', | |||
0x34 => '8E5E42', | |||
0x35 => 'A0627A', | |||
0x36 => '624FAC', | |||
0x37 => '969696', | |||
0x38 => '1D2FBE', | |||
0x39 => '286676', | |||
0x3A => '004500', | |||
0x3B => '453E01', | |||
0x3C => '6A2813', | |||
0x3D => '85396A', | |||
0x3E => '4A3285', | |||
0x3F => '424242', | |||
); | |||
/** | |||
* Map color array from BIFF5 built-in color index | |||
* | |||
* @param int $color | |||
* @return array | |||
*/ | |||
public static function lookup($color) | |||
{ | |||
if (isset(self::$map[$color])) { | |||
return array('rgb' => self::$map[$color]); | |||
} | |||
return array('rgb' => '000000'); | |||
} | |||
} |
@ -0,0 +1,77 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_Color_BIFF8 | |||
{ | |||
protected static $map = array( | |||
0x08 => '000000', | |||
0x09 => 'FFFFFF', | |||
0x0A => 'FF0000', | |||
0x0B => '00FF00', | |||
0x0C => '0000FF', | |||
0x0D => 'FFFF00', | |||
0x0E => 'FF00FF', | |||
0x0F => '00FFFF', | |||
0x10 => '800000', | |||
0x11 => '008000', | |||
0x12 => '000080', | |||
0x13 => '808000', | |||
0x14 => '800080', | |||
0x15 => '008080', | |||
0x16 => 'C0C0C0', | |||
0x17 => '808080', | |||
0x18 => '9999FF', | |||
0x19 => '993366', | |||
0x1A => 'FFFFCC', | |||
0x1B => 'CCFFFF', | |||
0x1C => '660066', | |||
0x1D => 'FF8080', | |||
0x1E => '0066CC', | |||
0x1F => 'CCCCFF', | |||
0x20 => '000080', | |||
0x21 => 'FF00FF', | |||
0x22 => 'FFFF00', | |||
0x23 => '00FFFF', | |||
0x24 => '800080', | |||
0x25 => '800000', | |||
0x26 => '008080', | |||
0x27 => '0000FF', | |||
0x28 => '00CCFF', | |||
0x29 => 'CCFFFF', | |||
0x2A => 'CCFFCC', | |||
0x2B => 'FFFF99', | |||
0x2C => '99CCFF', | |||
0x2D => 'FF99CC', | |||
0x2E => 'CC99FF', | |||
0x2F => 'FFCC99', | |||
0x30 => '3366FF', | |||
0x31 => '33CCCC', | |||
0x32 => '99CC00', | |||
0x33 => 'FFCC00', | |||
0x34 => 'FF9900', | |||
0x35 => 'FF6600', | |||
0x36 => '666699', | |||
0x37 => '969696', | |||
0x38 => '003366', | |||
0x39 => '339966', | |||
0x3A => '003300', | |||
0x3B => '333300', | |||
0x3C => '993300', | |||
0x3D => '993366', | |||
0x3E => '333399', | |||
0x3F => '333333', | |||
); | |||
/** | |||
* Map color array from BIFF8 built-in color index | |||
* | |||
* @param int $color | |||
* @return array | |||
*/ | |||
public static function lookup($color) | |||
{ | |||
if (isset(self::$map[$color])) { | |||
return array('rgb' => self::$map[$color]); | |||
} | |||
return array('rgb' => '000000'); | |||
} | |||
} |
@ -0,0 +1,31 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_Color_BuiltIn | |||
{ | |||
protected static $map = array( | |||
0x00 => '000000', | |||
0x01 => 'FFFFFF', | |||
0x02 => 'FF0000', | |||
0x03 => '00FF00', | |||
0x04 => '0000FF', | |||
0x05 => 'FFFF00', | |||
0x06 => 'FF00FF', | |||
0x07 => '00FFFF', | |||
0x40 => '000000', // system window text color | |||
0x41 => 'FFFFFF', // system window background color | |||
); | |||
/** | |||
* Map built-in color to RGB value | |||
* | |||
* @param int $color Indexed color | |||
* @return array | |||
*/ | |||
public static function lookup($color) | |||
{ | |||
if (isset(self::$map[$color])) { | |||
return array('rgb' => self::$map[$color]); | |||
} | |||
return array('rgb' => '000000'); | |||
} | |||
} |
@ -0,0 +1,28 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_ErrorCode | |||
{ | |||
protected static $map = array( | |||
0x00 => '#NULL!', | |||
0x07 => '#DIV/0!', | |||
0x0F => '#VALUE!', | |||
0x17 => '#REF!', | |||
0x1D => '#NAME?', | |||
0x24 => '#NUM!', | |||
0x2A => '#N/A', | |||
); | |||
/** | |||
* Map error code, e.g. '#N/A' | |||
* | |||
* @param int $code | |||
* @return string | |||
*/ | |||
public static function lookup($code) | |||
{ | |||
if (isset(self::$map[$code])) { | |||
return self::$map[$code]; | |||
} | |||
return false; | |||
} | |||
} |
@ -0,0 +1,669 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Reader_Excel5_Escher | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader_Excel5 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_Excel5_Escher | |||
{ | |||
const DGGCONTAINER = 0xF000; | |||
const BSTORECONTAINER = 0xF001; | |||
const DGCONTAINER = 0xF002; | |||
const SPGRCONTAINER = 0xF003; | |||
const SPCONTAINER = 0xF004; | |||
const DGG = 0xF006; | |||
const BSE = 0xF007; | |||
const DG = 0xF008; | |||
const SPGR = 0xF009; | |||
const SP = 0xF00A; | |||
const OPT = 0xF00B; | |||
const CLIENTTEXTBOX = 0xF00D; | |||
const CLIENTANCHOR = 0xF010; | |||
const CLIENTDATA = 0xF011; | |||
const BLIPJPEG = 0xF01D; | |||
const BLIPPNG = 0xF01E; | |||
const SPLITMENUCOLORS = 0xF11E; | |||
const TERTIARYOPT = 0xF122; | |||
/** | |||
* Escher stream data (binary) | |||
* | |||
* @var string | |||
*/ | |||
private $data; | |||
/** | |||
* Size in bytes of the Escher stream data | |||
* | |||
* @var int | |||
*/ | |||
private $dataSize; | |||
/** | |||
* Current position of stream pointer in Escher stream data | |||
* | |||
* @var int | |||
*/ | |||
private $pos; | |||
/** | |||
* The object to be returned by the reader. Modified during load. | |||
* | |||
* @var mixed | |||
*/ | |||
private $object; | |||
/** | |||
* Create a new PHPExcel_Reader_Excel5_Escher instance | |||
* | |||
* @param mixed $object | |||
*/ | |||
public function __construct($object) | |||
{ | |||
$this->object = $object; | |||
} | |||
/** | |||
* Load Escher stream data. May be a partial Escher stream. | |||
* | |||
* @param string $data | |||
*/ | |||
public function load($data) | |||
{ | |||
$this->data = $data; | |||
// total byte size of Excel data (workbook global substream + sheet substreams) | |||
$this->dataSize = strlen($this->data); | |||
$this->pos = 0; | |||
// Parse Escher stream | |||
while ($this->pos < $this->dataSize) { | |||
// offset: 2; size: 2: Record Type | |||
$fbt = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos + 2); | |||
switch ($fbt) { | |||
case self::DGGCONTAINER: | |||
$this->readDggContainer(); | |||
break; | |||
case self::DGG: | |||
$this->readDgg(); | |||
break; | |||
case self::BSTORECONTAINER: | |||
$this->readBstoreContainer(); | |||
break; | |||
case self::BSE: | |||
$this->readBSE(); | |||
break; | |||
case self::BLIPJPEG: | |||
$this->readBlipJPEG(); | |||
break; | |||
case self::BLIPPNG: | |||
$this->readBlipPNG(); | |||
break; | |||
case self::OPT: | |||
$this->readOPT(); | |||
break; | |||
case self::TERTIARYOPT: | |||
$this->readTertiaryOPT(); | |||
break; | |||
case self::SPLITMENUCOLORS: | |||
$this->readSplitMenuColors(); | |||
break; | |||
case self::DGCONTAINER: | |||
$this->readDgContainer(); | |||
break; | |||
case self::DG: | |||
$this->readDg(); | |||
break; | |||
case self::SPGRCONTAINER: | |||
$this->readSpgrContainer(); | |||
break; | |||
case self::SPCONTAINER: | |||
$this->readSpContainer(); | |||
break; | |||
case self::SPGR: | |||
$this->readSpgr(); | |||
break; | |||
case self::SP: | |||
$this->readSp(); | |||
break; | |||
case self::CLIENTTEXTBOX: | |||
$this->readClientTextbox(); | |||
break; | |||
case self::CLIENTANCHOR: | |||
$this->readClientAnchor(); | |||
break; | |||
case self::CLIENTDATA: | |||
$this->readClientData(); | |||
break; | |||
default: | |||
$this->readDefault(); | |||
break; | |||
} | |||
} | |||
return $this->object; | |||
} | |||
/** | |||
* Read a generic record | |||
*/ | |||
private function readDefault() | |||
{ | |||
// offset 0; size: 2; recVer and recInstance | |||
$verInstance = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos); | |||
// offset: 2; size: 2: Record Type | |||
$fbt = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos + 2); | |||
// bit: 0-3; mask: 0x000F; recVer | |||
$recVer = (0x000F & $verInstance) >> 0; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read DggContainer record (Drawing Group Container) | |||
*/ | |||
private function readDggContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$dggContainer = new PHPExcel_Shared_Escher_DggContainer(); | |||
$this->object->setDggContainer($dggContainer); | |||
$reader = new PHPExcel_Reader_Excel5_Escher($dggContainer); | |||
$reader->load($recordData); | |||
} | |||
/** | |||
* Read Dgg record (Drawing Group) | |||
*/ | |||
private function readDgg() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read BstoreContainer record (Blip Store Container) | |||
*/ | |||
private function readBstoreContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); | |||
$this->object->setBstoreContainer($bstoreContainer); | |||
$reader = new PHPExcel_Reader_Excel5_Escher($bstoreContainer); | |||
$reader->load($recordData); | |||
} | |||
/** | |||
* Read BSE record | |||
*/ | |||
private function readBSE() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// add BSE to BstoreContainer | |||
$BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); | |||
$this->object->addBSE($BSE); | |||
$BSE->setBLIPType($recInstance); | |||
// offset: 0; size: 1; btWin32 (MSOBLIPTYPE) | |||
$btWin32 = ord($recordData[0]); | |||
// offset: 1; size: 1; btWin32 (MSOBLIPTYPE) | |||
$btMacOS = ord($recordData[1]); | |||
// offset: 2; size: 16; MD4 digest | |||
$rgbUid = substr($recordData, 2, 16); | |||
// offset: 18; size: 2; tag | |||
$tag = PHPExcel_Reader_Excel5::getInt2d($recordData, 18); | |||
// offset: 20; size: 4; size of BLIP in bytes | |||
$size = PHPExcel_Reader_Excel5::getInt4d($recordData, 20); | |||
// offset: 24; size: 4; number of references to this BLIP | |||
$cRef = PHPExcel_Reader_Excel5::getInt4d($recordData, 24); | |||
// offset: 28; size: 4; MSOFO file offset | |||
$foDelay = PHPExcel_Reader_Excel5::getInt4d($recordData, 28); | |||
// offset: 32; size: 1; unused1 | |||
$unused1 = ord($recordData[32]); | |||
// offset: 33; size: 1; size of nameData in bytes (including null terminator) | |||
$cbName = ord($recordData[33]); | |||
// offset: 34; size: 1; unused2 | |||
$unused2 = ord($recordData[34]); | |||
// offset: 35; size: 1; unused3 | |||
$unused3 = ord($recordData[35]); | |||
// offset: 36; size: $cbName; nameData | |||
$nameData = substr($recordData, 36, $cbName); | |||
// offset: 36 + $cbName, size: var; the BLIP data | |||
$blipData = substr($recordData, 36 + $cbName); | |||
// record is a container, read contents | |||
$reader = new PHPExcel_Reader_Excel5_Escher($BSE); | |||
$reader->load($blipData); | |||
} | |||
/** | |||
* Read BlipJPEG record. Holds raw JPEG image data | |||
*/ | |||
private function readBlipJPEG() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
$pos = 0; | |||
// offset: 0; size: 16; rgbUid1 (MD4 digest of) | |||
$rgbUid1 = substr($recordData, 0, 16); | |||
$pos += 16; | |||
// offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 | |||
if (in_array($recInstance, array(0x046B, 0x06E3))) { | |||
$rgbUid2 = substr($recordData, 16, 16); | |||
$pos += 16; | |||
} | |||
// offset: var; size: 1; tag | |||
$tag = ord($recordData[$pos]); | |||
$pos += 1; | |||
// offset: var; size: var; the raw image data | |||
$data = substr($recordData, $pos); | |||
$blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); | |||
$blip->setData($data); | |||
$this->object->setBlip($blip); | |||
} | |||
/** | |||
* Read BlipPNG record. Holds raw PNG image data | |||
*/ | |||
private function readBlipPNG() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
$pos = 0; | |||
// offset: 0; size: 16; rgbUid1 (MD4 digest of) | |||
$rgbUid1 = substr($recordData, 0, 16); | |||
$pos += 16; | |||
// offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 | |||
if ($recInstance == 0x06E1) { | |||
$rgbUid2 = substr($recordData, 16, 16); | |||
$pos += 16; | |||
} | |||
// offset: var; size: 1; tag | |||
$tag = ord($recordData[$pos]); | |||
$pos += 1; | |||
// offset: var; size: var; the raw image data | |||
$data = substr($recordData, $pos); | |||
$blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); | |||
$blip->setData($data); | |||
$this->object->setBlip($blip); | |||
} | |||
/** | |||
* Read OPT record. This record may occur within DggContainer record or SpContainer | |||
*/ | |||
private function readOPT() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
$this->readOfficeArtRGFOPTE($recordData, $recInstance); | |||
} | |||
/** | |||
* Read TertiaryOPT record | |||
*/ | |||
private function readTertiaryOPT() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read SplitMenuColors record | |||
*/ | |||
private function readSplitMenuColors() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read DgContainer record (Drawing Container) | |||
*/ | |||
private function readDgContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$dgContainer = new PHPExcel_Shared_Escher_DgContainer(); | |||
$this->object->setDgContainer($dgContainer); | |||
$reader = new PHPExcel_Reader_Excel5_Escher($dgContainer); | |||
$escher = $reader->load($recordData); | |||
} | |||
/** | |||
* Read Dg record (Drawing) | |||
*/ | |||
private function readDg() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read SpgrContainer record (Shape Group Container) | |||
*/ | |||
private function readSpgrContainer() | |||
{ | |||
// context is either context DgContainer or SpgrContainer | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); | |||
if ($this->object instanceof PHPExcel_Shared_Escher_DgContainer) { | |||
// DgContainer | |||
$this->object->setSpgrContainer($spgrContainer); | |||
} else { | |||
// SpgrContainer | |||
$this->object->addChild($spgrContainer); | |||
} | |||
$reader = new PHPExcel_Reader_Excel5_Escher($spgrContainer); | |||
$escher = $reader->load($recordData); | |||
} | |||
/** | |||
* Read SpContainer record (Shape Container) | |||
*/ | |||
private function readSpContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// add spContainer to spgrContainer | |||
$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); | |||
$this->object->addChild($spContainer); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$reader = new PHPExcel_Reader_Excel5_Escher($spContainer); | |||
$escher = $reader->load($recordData); | |||
} | |||
/** | |||
* Read Spgr record (Shape Group) | |||
*/ | |||
private function readSpgr() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read Sp record (Shape) | |||
*/ | |||
private function readSp() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read ClientTextbox record | |||
*/ | |||
private function readClientTextbox() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read ClientAnchor record. This record holds information about where the shape is anchored in worksheet | |||
*/ | |||
private function readClientAnchor() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// offset: 2; size: 2; upper-left corner column index (0-based) | |||
$c1 = PHPExcel_Reader_Excel5::getInt2d($recordData, 2); | |||
// offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width | |||
$startOffsetX = PHPExcel_Reader_Excel5::getInt2d($recordData, 4); | |||
// offset: 6; size: 2; upper-left corner row index (0-based) | |||
$r1 = PHPExcel_Reader_Excel5::getInt2d($recordData, 6); | |||
// offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height | |||
$startOffsetY = PHPExcel_Reader_Excel5::getInt2d($recordData, 8); | |||
// offset: 10; size: 2; bottom-right corner column index (0-based) | |||
$c2 = PHPExcel_Reader_Excel5::getInt2d($recordData, 10); | |||
// offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width | |||
$endOffsetX = PHPExcel_Reader_Excel5::getInt2d($recordData, 12); | |||
// offset: 14; size: 2; bottom-right corner row index (0-based) | |||
$r2 = PHPExcel_Reader_Excel5::getInt2d($recordData, 14); | |||
// offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height | |||
$endOffsetY = PHPExcel_Reader_Excel5::getInt2d($recordData, 16); | |||
// set the start coordinates | |||
$this->object->setStartCoordinates(PHPExcel_Cell::stringFromColumnIndex($c1) . ($r1 + 1)); | |||
// set the start offsetX | |||
$this->object->setStartOffsetX($startOffsetX); | |||
// set the start offsetY | |||
$this->object->setStartOffsetY($startOffsetY); | |||
// set the end coordinates | |||
$this->object->setEndCoordinates(PHPExcel_Cell::stringFromColumnIndex($c2) . ($r2 + 1)); | |||
// set the end offsetX | |||
$this->object->setEndOffsetX($endOffsetX); | |||
// set the end offsetY | |||
$this->object->setEndOffsetY($endOffsetY); | |||
} | |||
/** | |||
* Read ClientData record | |||
*/ | |||
private function readClientData() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read OfficeArtRGFOPTE table of property-value pairs | |||
* | |||
* @param string $data Binary data | |||
* @param int $n Number of properties | |||
*/ | |||
private function readOfficeArtRGFOPTE($data, $n) | |||
{ | |||
$splicedComplexData = substr($data, 6 * $n); | |||
// loop through property-value pairs | |||
for ($i = 0; $i < $n; ++$i) { | |||
// read 6 bytes at a time | |||
$fopte = substr($data, 6 * $i, 6); | |||
// offset: 0; size: 2; opid | |||
$opid = PHPExcel_Reader_Excel5::getInt2d($fopte, 0); | |||
// bit: 0-13; mask: 0x3FFF; opid.opid | |||
$opidOpid = (0x3FFF & $opid) >> 0; | |||
// bit: 14; mask 0x4000; 1 = value in op field is BLIP identifier | |||
$opidFBid = (0x4000 & $opid) >> 14; | |||
// bit: 15; mask 0x8000; 1 = this is a complex property, op field specifies size of complex data | |||
$opidFComplex = (0x8000 & $opid) >> 15; | |||
// offset: 2; size: 4; the value for this property | |||
$op = PHPExcel_Reader_Excel5::getInt4d($fopte, 2); | |||
if ($opidFComplex) { | |||
$complexData = substr($splicedComplexData, 0, $op); | |||
$splicedComplexData = substr($splicedComplexData, $op); | |||
// we store string value with complex data | |||
$value = $complexData; | |||
} else { | |||
// we store integer value | |||
$value = $op; | |||
} | |||
$this->object->setOPT($opidOpid, $value); | |||
} | |||
} | |||
} |
@ -0,0 +1,669 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Reader_Excel5_Escher | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader_Excel5 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_Excel5_Escher | |||
{ | |||
const DGGCONTAINER = 0xF000; | |||
const BSTORECONTAINER = 0xF001; | |||
const DGCONTAINER = 0xF002; | |||
const SPGRCONTAINER = 0xF003; | |||
const SPCONTAINER = 0xF004; | |||
const DGG = 0xF006; | |||
const BSE = 0xF007; | |||
const DG = 0xF008; | |||
const SPGR = 0xF009; | |||
const SP = 0xF00A; | |||
const OPT = 0xF00B; | |||
const CLIENTTEXTBOX = 0xF00D; | |||
const CLIENTANCHOR = 0xF010; | |||
const CLIENTDATA = 0xF011; | |||
const BLIPJPEG = 0xF01D; | |||
const BLIPPNG = 0xF01E; | |||
const SPLITMENUCOLORS = 0xF11E; | |||
const TERTIARYOPT = 0xF122; | |||
/** | |||
* Escher stream data (binary) | |||
* | |||
* @var string | |||
*/ | |||
private $data; | |||
/** | |||
* Size in bytes of the Escher stream data | |||
* | |||
* @var int | |||
*/ | |||
private $dataSize; | |||
/** | |||
* Current position of stream pointer in Escher stream data | |||
* | |||
* @var int | |||
*/ | |||
private $pos; | |||
/** | |||
* The object to be returned by the reader. Modified during load. | |||
* | |||
* @var mixed | |||
*/ | |||
private $object; | |||
/** | |||
* Create a new PHPExcel_Reader_Excel5_Escher instance | |||
* | |||
* @param mixed $object | |||
*/ | |||
public function __construct($object) | |||
{ | |||
$this->object = $object; | |||
} | |||
/** | |||
* Load Escher stream data. May be a partial Escher stream. | |||
* | |||
* @param string $data | |||
*/ | |||
public function load($data) | |||
{ | |||
$this->data = $data; | |||
// total byte size of Excel data (workbook global substream + sheet substreams) | |||
$this->dataSize = strlen($this->data); | |||
$this->pos = 0; | |||
// Parse Escher stream | |||
while ($this->pos < $this->dataSize) { | |||
// offset: 2; size: 2: Record Type | |||
$fbt = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos + 2); | |||
switch ($fbt) { | |||
case self::DGGCONTAINER: | |||
$this->readDggContainer(); | |||
break; | |||
case self::DGG: | |||
$this->readDgg(); | |||
break; | |||
case self::BSTORECONTAINER: | |||
$this->readBstoreContainer(); | |||
break; | |||
case self::BSE: | |||
$this->readBSE(); | |||
break; | |||
case self::BLIPJPEG: | |||
$this->readBlipJPEG(); | |||
break; | |||
case self::BLIPPNG: | |||
$this->readBlipPNG(); | |||
break; | |||
case self::OPT: | |||
$this->readOPT(); | |||
break; | |||
case self::TERTIARYOPT: | |||
$this->readTertiaryOPT(); | |||
break; | |||
case self::SPLITMENUCOLORS: | |||
$this->readSplitMenuColors(); | |||
break; | |||
case self::DGCONTAINER: | |||
$this->readDgContainer(); | |||
break; | |||
case self::DG: | |||
$this->readDg(); | |||
break; | |||
case self::SPGRCONTAINER: | |||
$this->readSpgrContainer(); | |||
break; | |||
case self::SPCONTAINER: | |||
$this->readSpContainer(); | |||
break; | |||
case self::SPGR: | |||
$this->readSpgr(); | |||
break; | |||
case self::SP: | |||
$this->readSp(); | |||
break; | |||
case self::CLIENTTEXTBOX: | |||
$this->readClientTextbox(); | |||
break; | |||
case self::CLIENTANCHOR: | |||
$this->readClientAnchor(); | |||
break; | |||
case self::CLIENTDATA: | |||
$this->readClientData(); | |||
break; | |||
default: | |||
$this->readDefault(); | |||
break; | |||
} | |||
} | |||
return $this->object; | |||
} | |||
/** | |||
* Read a generic record | |||
*/ | |||
private function readDefault() | |||
{ | |||
// offset 0; size: 2; recVer and recInstance | |||
$verInstance = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos); | |||
// offset: 2; size: 2: Record Type | |||
$fbt = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos + 2); | |||
// bit: 0-3; mask: 0x000F; recVer | |||
$recVer = (0x000F & $verInstance) >> 0; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read DggContainer record (Drawing Group Container) | |||
*/ | |||
private function readDggContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$dggContainer = new PHPExcel_Shared_Escher_DggContainer(); | |||
$this->object->setDggContainer($dggContainer); | |||
$reader = new PHPExcel_Reader_Excel5_Escher($dggContainer); | |||
$reader->load($recordData); | |||
} | |||
/** | |||
* Read Dgg record (Drawing Group) | |||
*/ | |||
private function readDgg() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read BstoreContainer record (Blip Store Container) | |||
*/ | |||
private function readBstoreContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); | |||
$this->object->setBstoreContainer($bstoreContainer); | |||
$reader = new PHPExcel_Reader_Excel5_Escher($bstoreContainer); | |||
$reader->load($recordData); | |||
} | |||
/** | |||
* Read BSE record | |||
*/ | |||
private function readBSE() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// add BSE to BstoreContainer | |||
$BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); | |||
$this->object->addBSE($BSE); | |||
$BSE->setBLIPType($recInstance); | |||
// offset: 0; size: 1; btWin32 (MSOBLIPTYPE) | |||
$btWin32 = ord($recordData[0]); | |||
// offset: 1; size: 1; btWin32 (MSOBLIPTYPE) | |||
$btMacOS = ord($recordData[1]); | |||
// offset: 2; size: 16; MD4 digest | |||
$rgbUid = substr($recordData, 2, 16); | |||
// offset: 18; size: 2; tag | |||
$tag = PHPExcel_Reader_Excel5::getInt2d($recordData, 18); | |||
// offset: 20; size: 4; size of BLIP in bytes | |||
$size = PHPExcel_Reader_Excel5::getInt4d($recordData, 20); | |||
// offset: 24; size: 4; number of references to this BLIP | |||
$cRef = PHPExcel_Reader_Excel5::getInt4d($recordData, 24); | |||
// offset: 28; size: 4; MSOFO file offset | |||
$foDelay = PHPExcel_Reader_Excel5::getInt4d($recordData, 28); | |||
// offset: 32; size: 1; unused1 | |||
$unused1 = ord($recordData{32}); | |||
// offset: 33; size: 1; size of nameData in bytes (including null terminator) | |||
$cbName = ord($recordData{33}); | |||
// offset: 34; size: 1; unused2 | |||
$unused2 = ord($recordData{34}); | |||
// offset: 35; size: 1; unused3 | |||
$unused3 = ord($recordData{35}); | |||
// offset: 36; size: $cbName; nameData | |||
$nameData = substr($recordData, 36, $cbName); | |||
// offset: 36 + $cbName, size: var; the BLIP data | |||
$blipData = substr($recordData, 36 + $cbName); | |||
// record is a container, read contents | |||
$reader = new PHPExcel_Reader_Excel5_Escher($BSE); | |||
$reader->load($blipData); | |||
} | |||
/** | |||
* Read BlipJPEG record. Holds raw JPEG image data | |||
*/ | |||
private function readBlipJPEG() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
$pos = 0; | |||
// offset: 0; size: 16; rgbUid1 (MD4 digest of) | |||
$rgbUid1 = substr($recordData, 0, 16); | |||
$pos += 16; | |||
// offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 | |||
if (in_array($recInstance, array(0x046B, 0x06E3))) { | |||
$rgbUid2 = substr($recordData, 16, 16); | |||
$pos += 16; | |||
} | |||
// offset: var; size: 1; tag | |||
$tag = ord($recordData{$pos}); | |||
$pos += 1; | |||
// offset: var; size: var; the raw image data | |||
$data = substr($recordData, $pos); | |||
$blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); | |||
$blip->setData($data); | |||
$this->object->setBlip($blip); | |||
} | |||
/** | |||
* Read BlipPNG record. Holds raw PNG image data | |||
*/ | |||
private function readBlipPNG() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
$pos = 0; | |||
// offset: 0; size: 16; rgbUid1 (MD4 digest of) | |||
$rgbUid1 = substr($recordData, 0, 16); | |||
$pos += 16; | |||
// offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 | |||
if ($recInstance == 0x06E1) { | |||
$rgbUid2 = substr($recordData, 16, 16); | |||
$pos += 16; | |||
} | |||
// offset: var; size: 1; tag | |||
$tag = ord($recordData{$pos}); | |||
$pos += 1; | |||
// offset: var; size: var; the raw image data | |||
$data = substr($recordData, $pos); | |||
$blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); | |||
$blip->setData($data); | |||
$this->object->setBlip($blip); | |||
} | |||
/** | |||
* Read OPT record. This record may occur within DggContainer record or SpContainer | |||
*/ | |||
private function readOPT() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
$this->readOfficeArtRGFOPTE($recordData, $recInstance); | |||
} | |||
/** | |||
* Read TertiaryOPT record | |||
*/ | |||
private function readTertiaryOPT() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read SplitMenuColors record | |||
*/ | |||
private function readSplitMenuColors() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read DgContainer record (Drawing Container) | |||
*/ | |||
private function readDgContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$dgContainer = new PHPExcel_Shared_Escher_DgContainer(); | |||
$this->object->setDgContainer($dgContainer); | |||
$reader = new PHPExcel_Reader_Excel5_Escher($dgContainer); | |||
$escher = $reader->load($recordData); | |||
} | |||
/** | |||
* Read Dg record (Drawing) | |||
*/ | |||
private function readDg() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read SpgrContainer record (Shape Group Container) | |||
*/ | |||
private function readSpgrContainer() | |||
{ | |||
// context is either context DgContainer or SpgrContainer | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); | |||
if ($this->object instanceof PHPExcel_Shared_Escher_DgContainer) { | |||
// DgContainer | |||
$this->object->setSpgrContainer($spgrContainer); | |||
} else { | |||
// SpgrContainer | |||
$this->object->addChild($spgrContainer); | |||
} | |||
$reader = new PHPExcel_Reader_Excel5_Escher($spgrContainer); | |||
$escher = $reader->load($recordData); | |||
} | |||
/** | |||
* Read SpContainer record (Shape Container) | |||
*/ | |||
private function readSpContainer() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// add spContainer to spgrContainer | |||
$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); | |||
$this->object->addChild($spContainer); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// record is a container, read contents | |||
$reader = new PHPExcel_Reader_Excel5_Escher($spContainer); | |||
$escher = $reader->load($recordData); | |||
} | |||
/** | |||
* Read Spgr record (Shape Group) | |||
*/ | |||
private function readSpgr() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read Sp record (Shape) | |||
*/ | |||
private function readSp() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read ClientTextbox record | |||
*/ | |||
private function readClientTextbox() | |||
{ | |||
// offset: 0; size: 2; recVer and recInstance | |||
// bit: 4-15; mask: 0xFFF0; recInstance | |||
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4; | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read ClientAnchor record. This record holds information about where the shape is anchored in worksheet | |||
*/ | |||
private function readClientAnchor() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
// offset: 2; size: 2; upper-left corner column index (0-based) | |||
$c1 = PHPExcel_Reader_Excel5::getInt2d($recordData, 2); | |||
// offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width | |||
$startOffsetX = PHPExcel_Reader_Excel5::getInt2d($recordData, 4); | |||
// offset: 6; size: 2; upper-left corner row index (0-based) | |||
$r1 = PHPExcel_Reader_Excel5::getInt2d($recordData, 6); | |||
// offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height | |||
$startOffsetY = PHPExcel_Reader_Excel5::getInt2d($recordData, 8); | |||
// offset: 10; size: 2; bottom-right corner column index (0-based) | |||
$c2 = PHPExcel_Reader_Excel5::getInt2d($recordData, 10); | |||
// offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width | |||
$endOffsetX = PHPExcel_Reader_Excel5::getInt2d($recordData, 12); | |||
// offset: 14; size: 2; bottom-right corner row index (0-based) | |||
$r2 = PHPExcel_Reader_Excel5::getInt2d($recordData, 14); | |||
// offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height | |||
$endOffsetY = PHPExcel_Reader_Excel5::getInt2d($recordData, 16); | |||
// set the start coordinates | |||
$this->object->setStartCoordinates(PHPExcel_Cell::stringFromColumnIndex($c1) . ($r1 + 1)); | |||
// set the start offsetX | |||
$this->object->setStartOffsetX($startOffsetX); | |||
// set the start offsetY | |||
$this->object->setStartOffsetY($startOffsetY); | |||
// set the end coordinates | |||
$this->object->setEndCoordinates(PHPExcel_Cell::stringFromColumnIndex($c2) . ($r2 + 1)); | |||
// set the end offsetX | |||
$this->object->setEndOffsetX($endOffsetX); | |||
// set the end offsetY | |||
$this->object->setEndOffsetY($endOffsetY); | |||
} | |||
/** | |||
* Read ClientData record | |||
*/ | |||
private function readClientData() | |||
{ | |||
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4); | |||
$recordData = substr($this->data, $this->pos + 8, $length); | |||
// move stream pointer to next record | |||
$this->pos += 8 + $length; | |||
} | |||
/** | |||
* Read OfficeArtRGFOPTE table of property-value pairs | |||
* | |||
* @param string $data Binary data | |||
* @param int $n Number of properties | |||
*/ | |||
private function readOfficeArtRGFOPTE($data, $n) | |||
{ | |||
$splicedComplexData = substr($data, 6 * $n); | |||
// loop through property-value pairs | |||
for ($i = 0; $i < $n; ++$i) { | |||
// read 6 bytes at a time | |||
$fopte = substr($data, 6 * $i, 6); | |||
// offset: 0; size: 2; opid | |||
$opid = PHPExcel_Reader_Excel5::getInt2d($fopte, 0); | |||
// bit: 0-13; mask: 0x3FFF; opid.opid | |||
$opidOpid = (0x3FFF & $opid) >> 0; | |||
// bit: 14; mask 0x4000; 1 = value in op field is BLIP identifier | |||
$opidFBid = (0x4000 & $opid) >> 14; | |||
// bit: 15; mask 0x8000; 1 = this is a complex property, op field specifies size of complex data | |||
$opidFComplex = (0x8000 & $opid) >> 15; | |||
// offset: 2; size: 4; the value for this property | |||
$op = PHPExcel_Reader_Excel5::getInt4d($fopte, 2); | |||
if ($opidFComplex) { | |||
$complexData = substr($splicedComplexData, 0, $op); | |||
$splicedComplexData = substr($splicedComplexData, $op); | |||
// we store string value with complex data | |||
$value = $complexData; | |||
} else { | |||
// we store integer value | |||
$value = $op; | |||
} | |||
$this->object->setOPT($opidOpid, $value); | |||
} | |||
} | |||
} |
@ -0,0 +1,203 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Reader_Excel5_MD5 | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader_Excel5 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_Excel5_MD5 | |||
{ | |||
// Context | |||
private $a; | |||
private $b; | |||
private $c; | |||
private $d; | |||
/** | |||
* MD5 stream constructor | |||
*/ | |||
public function __construct() | |||
{ | |||
$this->reset(); | |||
} | |||
/** | |||
* Reset the MD5 stream context | |||
*/ | |||
public function reset() | |||
{ | |||
$this->a = 0x67452301; | |||
$this->b = 0xEFCDAB89; | |||
$this->c = 0x98BADCFE; | |||
$this->d = 0x10325476; | |||
} | |||
/** | |||
* Get MD5 stream context | |||
* | |||
* @return string | |||
*/ | |||
public function getContext() | |||
{ | |||
$s = ''; | |||
foreach (array('a', 'b', 'c', 'd') as $i) { | |||
$v = $this->{$i}; | |||
$s .= chr($v & 0xff); | |||
$s .= chr(($v >> 8) & 0xff); | |||
$s .= chr(($v >> 16) & 0xff); | |||
$s .= chr(($v >> 24) & 0xff); | |||
} | |||
return $s; | |||
} | |||
/** | |||
* Add data to context | |||
* | |||
* @param string $data Data to add | |||
*/ | |||
public function add($data) | |||
{ | |||
$words = array_values(unpack('V16', $data)); | |||
$A = $this->a; | |||
$B = $this->b; | |||
$C = $this->c; | |||
$D = $this->d; | |||
$F = array('PHPExcel_Reader_Excel5_MD5','f'); | |||
$G = array('PHPExcel_Reader_Excel5_MD5','g'); | |||
$H = array('PHPExcel_Reader_Excel5_MD5','h'); | |||
$I = array('PHPExcel_Reader_Excel5_MD5','i'); | |||
/* ROUND 1 */ | |||
self::step($F, $A, $B, $C, $D, $words[0], 7, 0xd76aa478); | |||
self::step($F, $D, $A, $B, $C, $words[1], 12, 0xe8c7b756); | |||
self::step($F, $C, $D, $A, $B, $words[2], 17, 0x242070db); | |||
self::step($F, $B, $C, $D, $A, $words[3], 22, 0xc1bdceee); | |||
self::step($F, $A, $B, $C, $D, $words[4], 7, 0xf57c0faf); | |||
self::step($F, $D, $A, $B, $C, $words[5], 12, 0x4787c62a); | |||
self::step($F, $C, $D, $A, $B, $words[6], 17, 0xa8304613); | |||
self::step($F, $B, $C, $D, $A, $words[7], 22, 0xfd469501); | |||
self::step($F, $A, $B, $C, $D, $words[8], 7, 0x698098d8); | |||
self::step($F, $D, $A, $B, $C, $words[9], 12, 0x8b44f7af); | |||
self::step($F, $C, $D, $A, $B, $words[10], 17, 0xffff5bb1); | |||
self::step($F, $B, $C, $D, $A, $words[11], 22, 0x895cd7be); | |||
self::step($F, $A, $B, $C, $D, $words[12], 7, 0x6b901122); | |||
self::step($F, $D, $A, $B, $C, $words[13], 12, 0xfd987193); | |||
self::step($F, $C, $D, $A, $B, $words[14], 17, 0xa679438e); | |||
self::step($F, $B, $C, $D, $A, $words[15], 22, 0x49b40821); | |||
/* ROUND 2 */ | |||
self::step($G, $A, $B, $C, $D, $words[1], 5, 0xf61e2562); | |||
self::step($G, $D, $A, $B, $C, $words[6], 9, 0xc040b340); | |||
self::step($G, $C, $D, $A, $B, $words[11], 14, 0x265e5a51); | |||
self::step($G, $B, $C, $D, $A, $words[0], 20, 0xe9b6c7aa); | |||
self::step($G, $A, $B, $C, $D, $words[5], 5, 0xd62f105d); | |||
self::step($G, $D, $A, $B, $C, $words[10], 9, 0x02441453); | |||
self::step($G, $C, $D, $A, $B, $words[15], 14, 0xd8a1e681); | |||
self::step($G, $B, $C, $D, $A, $words[4], 20, 0xe7d3fbc8); | |||
self::step($G, $A, $B, $C, $D, $words[9], 5, 0x21e1cde6); | |||
self::step($G, $D, $A, $B, $C, $words[14], 9, 0xc33707d6); | |||
self::step($G, $C, $D, $A, $B, $words[3], 14, 0xf4d50d87); | |||
self::step($G, $B, $C, $D, $A, $words[8], 20, 0x455a14ed); | |||
self::step($G, $A, $B, $C, $D, $words[13], 5, 0xa9e3e905); | |||
self::step($G, $D, $A, $B, $C, $words[2], 9, 0xfcefa3f8); | |||
self::step($G, $C, $D, $A, $B, $words[7], 14, 0x676f02d9); | |||
self::step($G, $B, $C, $D, $A, $words[12], 20, 0x8d2a4c8a); | |||
/* ROUND 3 */ | |||
self::step($H, $A, $B, $C, $D, $words[5], 4, 0xfffa3942); | |||
self::step($H, $D, $A, $B, $C, $words[8], 11, 0x8771f681); | |||
self::step($H, $C, $D, $A, $B, $words[11], 16, 0x6d9d6122); | |||
self::step($H, $B, $C, $D, $A, $words[14], 23, 0xfde5380c); | |||
self::step($H, $A, $B, $C, $D, $words[1], 4, 0xa4beea44); | |||
self::step($H, $D, $A, $B, $C, $words[4], 11, 0x4bdecfa9); | |||
self::step($H, $C, $D, $A, $B, $words[7], 16, 0xf6bb4b60); | |||
self::step($H, $B, $C, $D, $A, $words[10], 23, 0xbebfbc70); | |||
self::step($H, $A, $B, $C, $D, $words[13], 4, 0x289b7ec6); | |||
self::step($H, $D, $A, $B, $C, $words[0], 11, 0xeaa127fa); | |||
self::step($H, $C, $D, $A, $B, $words[3], 16, 0xd4ef3085); | |||
self::step($H, $B, $C, $D, $A, $words[6], 23, 0x04881d05); | |||
self::step($H, $A, $B, $C, $D, $words[9], 4, 0xd9d4d039); | |||
self::step($H, $D, $A, $B, $C, $words[12], 11, 0xe6db99e5); | |||
self::step($H, $C, $D, $A, $B, $words[15], 16, 0x1fa27cf8); | |||
self::step($H, $B, $C, $D, $A, $words[2], 23, 0xc4ac5665); | |||
/* ROUND 4 */ | |||
self::step($I, $A, $B, $C, $D, $words[0], 6, 0xf4292244); | |||
self::step($I, $D, $A, $B, $C, $words[7], 10, 0x432aff97); | |||
self::step($I, $C, $D, $A, $B, $words[14], 15, 0xab9423a7); | |||
self::step($I, $B, $C, $D, $A, $words[5], 21, 0xfc93a039); | |||
self::step($I, $A, $B, $C, $D, $words[12], 6, 0x655b59c3); | |||
self::step($I, $D, $A, $B, $C, $words[3], 10, 0x8f0ccc92); | |||
self::step($I, $C, $D, $A, $B, $words[10], 15, 0xffeff47d); | |||
self::step($I, $B, $C, $D, $A, $words[1], 21, 0x85845dd1); | |||
self::step($I, $A, $B, $C, $D, $words[8], 6, 0x6fa87e4f); | |||
self::step($I, $D, $A, $B, $C, $words[15], 10, 0xfe2ce6e0); | |||
self::step($I, $C, $D, $A, $B, $words[6], 15, 0xa3014314); | |||
self::step($I, $B, $C, $D, $A, $words[13], 21, 0x4e0811a1); | |||
self::step($I, $A, $B, $C, $D, $words[4], 6, 0xf7537e82); | |||
self::step($I, $D, $A, $B, $C, $words[11], 10, 0xbd3af235); | |||
self::step($I, $C, $D, $A, $B, $words[2], 15, 0x2ad7d2bb); | |||
self::step($I, $B, $C, $D, $A, $words[9], 21, 0xeb86d391); | |||
$this->a = ($this->a + $A) & 0xffffffff; | |||
$this->b = ($this->b + $B) & 0xffffffff; | |||
$this->c = ($this->c + $C) & 0xffffffff; | |||
$this->d = ($this->d + $D) & 0xffffffff; | |||
} | |||
private static function f($X, $Y, $Z) | |||
{ | |||
return (($X & $Y) | ((~ $X) & $Z)); // X AND Y OR NOT X AND Z | |||
} | |||
private static function g($X, $Y, $Z) | |||
{ | |||
return (($X & $Z) | ($Y & (~ $Z))); // X AND Z OR Y AND NOT Z | |||
} | |||
private static function h($X, $Y, $Z) | |||
{ | |||
return ($X ^ $Y ^ $Z); // X XOR Y XOR Z | |||
} | |||
private static function i($X, $Y, $Z) | |||
{ | |||
return ($Y ^ ($X | (~ $Z))) ; // Y XOR (X OR NOT Z) | |||
} | |||
private static function step($func, &$A, $B, $C, $D, $M, $s, $t) | |||
{ | |||
$A = ($A + call_user_func($func, $B, $C, $D) + $M + $t) & 0xffffffff; | |||
$A = self::rotate($A, $s); | |||
$A = ($B + $A) & 0xffffffff; | |||
} | |||
private static function rotate($decimal, $bits) | |||
{ | |||
$binary = str_pad(decbin($decimal), 32, "0", STR_PAD_LEFT); | |||
return bindec(substr($binary, $bits).substr($binary, 0, $bits)); | |||
} | |||
} |
@ -0,0 +1,81 @@ | |||
<?php | |||
/** | |||
* PHPExcel_Reader_Excel5_RC4 | |||
* | |||
* Copyright (c) 2006 - 2015 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_Reader_Excel5 | |||
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel) | |||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL | |||
* @version ##VERSION##, ##DATE## | |||
*/ | |||
class PHPExcel_Reader_Excel5_RC4 | |||
{ | |||
// Context | |||
protected $s = array(); | |||
protected $i = 0; | |||
protected $j = 0; | |||
/** | |||
* RC4 stream decryption/encryption constrcutor | |||
* | |||
* @param string $key Encryption key/passphrase | |||
*/ | |||
public function __construct($key) | |||
{ | |||
$len = strlen($key); | |||
for ($this->i = 0; $this->i < 256; $this->i++) { | |||
$this->s[$this->i] = $this->i; | |||
} | |||
$this->j = 0; | |||
for ($this->i = 0; $this->i < 256; $this->i++) { | |||
$this->j = ($this->j + $this->s[$this->i] + ord($key[$this->i % $len])) % 256; | |||
$t = $this->s[$this->i]; | |||
$this->s[$this->i] = $this->s[$this->j]; | |||
$this->s[$this->j] = $t; | |||
} | |||
$this->i = $this->j = 0; | |||
} | |||
/** | |||
* Symmetric decryption/encryption function | |||
* | |||
* @param string $data Data to encrypt/decrypt | |||
* | |||
* @return string | |||
*/ | |||
public function RC4($data) | |||
{ | |||
$len = strlen($data); | |||
for ($c = 0; $c < $len; $c++) { | |||
$this->i = ($this->i + 1) % 256; | |||
$this->j = ($this->j + $this->s[$this->i]) % 256; | |||
$t = $this->s[$this->i]; | |||
$this->s[$this->i] = $this->s[$this->j]; | |||
$this->s[$this->j] = $t; | |||
$t = ($this->s[$this->i] + $this->s[$this->j]) % 256; | |||
$data[$c] = chr(ord($data[$c]) ^ $this->s[$t]); | |||
} | |||
return $data; | |||
} | |||
} |
@ -0,0 +1,36 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_Style_Border | |||
{ | |||
protected static $map = array( | |||
0x00 => PHPExcel_Style_Border::BORDER_NONE, | |||
0x01 => PHPExcel_Style_Border::BORDER_THIN, | |||
0x02 => PHPExcel_Style_Border::BORDER_MEDIUM, | |||
0x03 => PHPExcel_Style_Border::BORDER_DASHED, | |||
0x04 => PHPExcel_Style_Border::BORDER_DOTTED, | |||
0x05 => PHPExcel_Style_Border::BORDER_THICK, | |||
0x06 => PHPExcel_Style_Border::BORDER_DOUBLE, | |||
0x07 => PHPExcel_Style_Border::BORDER_HAIR, | |||
0x08 => PHPExcel_Style_Border::BORDER_MEDIUMDASHED, | |||
0x09 => PHPExcel_Style_Border::BORDER_DASHDOT, | |||
0x0A => PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT, | |||
0x0B => PHPExcel_Style_Border::BORDER_DASHDOTDOT, | |||
0x0C => PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT, | |||
0x0D => PHPExcel_Style_Border::BORDER_SLANTDASHDOT, | |||
); | |||
/** | |||
* Map border style | |||
* OpenOffice documentation: 2.5.11 | |||
* | |||
* @param int $index | |||
* @return string | |||
*/ | |||
public static function lookup($index) | |||
{ | |||
if (isset(self::$map[$index])) { | |||
return self::$map[$index]; | |||
} | |||
return PHPExcel_Style_Border::BORDER_NONE; | |||
} | |||
} |
@ -0,0 +1,41 @@ | |||
<?php | |||
class PHPExcel_Reader_Excel5_Style_FillPattern | |||
{ | |||
protected static $map = array( | |||
0x00 => PHPExcel_Style_Fill::FILL_NONE, | |||
0x01 => PHPExcel_Style_Fill::FILL_SOLID, | |||
0x02 => PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY, | |||
0x03 => PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY, | |||
0x04 => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY, | |||
0x05 => PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL, | |||
0x06 => PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL, | |||
0x07 => PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN, | |||
0x08 => PHPExcel_Style_Fill::FILL_PATTERN_DARKUP, | |||
0x09 => PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID, | |||
0x0A => PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS, | |||
0x0B => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL, | |||
0x0C => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL, | |||
0x0D => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN, | |||
0x0E => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP, | |||
0x0F => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID, | |||
0x10 => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS, | |||
0x11 => PHPExcel_Style_Fill::FILL_PATTERN_GRAY125, | |||
0x12 => PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625, | |||
); | |||
/** | |||
* Get fill pattern from index | |||
* OpenOffice documentation: 2.5.12 | |||
* | |||
* @param int $index | |||
* @return string | |||
*/ | |||
public static function lookup($index) | |||
{ | |||
if (isset(self::$map[$index])) { | |||
return self::$map[$index]; | |||
} | |||
return PHPExcel_Style_Fill::FILL_NONE; | |||
} | |||
} |