For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

760 lines
20 KiB

<?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;
}
}