Rev 2388 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** PHPExcel** Copyright (c) 2006 - 2013 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 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL* @version ##VERSION##, ##DATE##*//** 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** @category PHPExcel* @package PHPExcel_Calculation* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)*/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;} // function setCompatibilityMode()/*** 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;} // function getCompatibilityMode()/*** 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;} // function setReturnDateType()/*** 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;} // function getReturnDateType()/*** DUMMY** @access public* @category Error Returns* @return string #Not Yet Implemented*/public static function DUMMY() {return '#Not Yet Implemented';} // function DUMMY()/*** DIV0** @access public* @category Error Returns* @return string #Not Yet Implemented*/public static function DIV0() {return self::$_errorCodes['divisionbyzero'];} // function DIV0()/*** 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'];} // function NA()/*** NaN** Returns the error value #NUM!** @access public* @category Error Returns* @return string #NUM!*/public static function NaN() {return self::$_errorCodes['num'];} // function NaN()/*** NAME** Returns the error value #NAME?** @access public* @category Error Returns* @return string #NAME?*/public static function NAME() {return self::$_errorCodes['name'];} // function NAME()/*** REF** Returns the error value #REF!** @access public* @category Error Returns* @return string #REF!*/public static function REF() {return self::$_errorCodes['reference'];} // function REF()/*** NULL** Returns the error value #NULL!** @access public* @category Error Returns* @return string #REF!*/public static function NULL() {return self::$_errorCodes['null'];} // function NULL()/*** VALUE** Returns the error value #VALUE!** @access public* @category Error Returns* @return string #VALUE!*/public static function VALUE() {return self::$_errorCodes['value'];} // function 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 = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); }return $operator.$operand;}} // function _ifCondition()/*** 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();} // function ERROR_TYPE()/*** 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);} // function IS_BLANK()/*** 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));} // function IS_ERR()/*** 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));} // function IS_ERROR()/*** IS_NA** @param mixed $value Value to check* @return boolean*/public static function IS_NA($value = '') {$value = self::flattenSingleValue($value);return ($value === self::NA());} // function IS_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();if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value))))return self::VALUE();return ($value % 2 == 0);} // function IS_EVEN()/*** 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();if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value))))return self::VALUE();return (abs($value) % 2 == 1);} // function IS_ODD()/*** 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);} // function IS_NUMBER()/*** 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);} // function IS_LOGICAL()/*** 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));} // function IS_TEXT()/*** IS_NONTEXT** @param mixed $value Value to check* @return boolean*/public static function IS_NONTEXT($value = NULL) {return !self::IS_TEXT($value);} // function IS_NONTEXT()/*** VERSION** @return string Version information*/public static function VERSION() {return 'PHPExcel ##VERSION##, ##DATE##';} // function VERSION()/*** 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;break;case 'boolean' :return (integer) $value;break;case 'string' :// Errorsif ((strlen($value) > 0) && ($value{0} == '#')) {return $value;}break;}return 0;} // function N()/*** 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)) {$a = array_keys($value);$a = array_pop($a);// Range of cells is an errorif (self::isCellValue($a)) {return 16;// Test for Matrix} elseif (self::isMatrixValue($a)) {return 64;}} elseif(empty($value)) {// Empty Cellreturn 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;break;} elseif(is_string($value)) {// Errorsif ((strlen($value) > 0) && ($value{0} == '#')) {return 16;}return 2;}return 0;} // function TYPE()/*** 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;} // function flattenArray()/*** 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;} // function flattenArrayIndexed()/*** 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;} // function flattenSingleValue()} // class PHPExcel_Calculation_Functions//// 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()}if (!function_exists('money_format')) {function money_format($format, $number) {$regex = array( '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?(?:#([0-9]+))?','(?:\.([0-9]+))?([in%])/');$regex = implode('', $regex);if (setlocale(LC_MONETARY, null) == '') {setlocale(LC_MONETARY, '');}$locale = localeconv();$number = floatval($number);if (!preg_match($regex, $format, $fmatch)) {trigger_error("No format specified or invalid format", E_USER_WARNING);return $number;}$flags = array( 'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ? $match[1] : ' ','nogroup' => preg_match('/\^/', $fmatch[1]) > 0,'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ? $match[0] : '+','nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,'isleft' => preg_match('/\-/', $fmatch[1]) > 0);$width = trim($fmatch[2]) ? (int)$fmatch[2] : 0;$left = trim($fmatch[3]) ? (int)$fmatch[3] : 0;$right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];$conversion = $fmatch[5];$positive = true;if ($number < 0) {$positive = false;$number *= -1;}$letter = $positive ? 'p' : 'n';$prefix = $suffix = $cprefix = $csuffix = $signal = '';if (!$positive) {$signal = $locale['negative_sign'];switch (true) {case $locale['n_sign_posn'] == 0 || $flags['usesignal'] == '(':$prefix = '(';$suffix = ')';break;case $locale['n_sign_posn'] == 1:$prefix = $signal;break;case $locale['n_sign_posn'] == 2:$suffix = $signal;break;case $locale['n_sign_posn'] == 3:$cprefix = $signal;break;case $locale['n_sign_posn'] == 4:$csuffix = $signal;break;}}if (!$flags['nosimbol']) {$currency = $cprefix;$currency .= ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']);$currency .= $csuffix;$currency = iconv('ISO-8859-1','UTF-8',$currency);} else {$currency = '';}$space = $locale["{$letter}_sep_by_space"] ? ' ' : '';if (!isset($locale['mon_decimal_point']) || empty($locale['mon_decimal_point'])) {$locale['mon_decimal_point'] = (!isset($locale['decimal_point']) || empty($locale['decimal_point'])) ?$locale['decimal_point'] :'.';}$number = number_format($number, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep'] );$number = explode($locale['mon_decimal_point'], $number);$n = strlen($prefix) + strlen($currency);if ($left > 0 && $left > $n) {if ($flags['isleft']) {$number[0] .= str_repeat($flags['fillchar'], $left - $n);} else {$number[0] = str_repeat($flags['fillchar'], $left - $n) . $number[0];}}$number = implode($locale['mon_decimal_point'], $number);if ($locale["{$letter}_cs_precedes"]) {$number = $prefix . $currency . $space . $number . $suffix;} else {$number = $prefix . $number . $space . $currency . $suffix;}if ($width > 0) {$number = str_pad($number, $width, $flags['fillchar'], $flags['isleft'] ? STR_PAD_RIGHT : STR_PAD_LEFT);}$format = str_replace($fmatch[0], $number, $format);return $format;} // function money_format()}//// 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 == '') {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;}}