Dateien nach "includes/PHPExcel/Classes/PHPExcel/Calculation" hochladen

This commit is contained in:
M_Viper 2024-03-10 15:25:57 +00:00
parent bfb52d24ac
commit 34ba63a0eb
16 changed files with 15944 additions and 0 deletions

View File

@ -0,0 +1,725 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 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');
}
/**
* PHPExcel_Calculation_Database
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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;
}
/**
* 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;
}
// 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::AVERAGE($colData);
} // function DAVERAGE()
/**
* 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;
}
// 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::COUNT($colData);
} // function DCOUNT()
/**
* 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($colData);
} // function DCOUNTA()
/**
* 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;
}
// 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
if (count($colData) > 1) {
return PHPExcel_Calculation_Functions::NaN();
}
return $colData[0];
} // function DGET()
/**
* 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;
}
// 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::MAX($colData);
} // function DMAX()
/**
* 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;
}
// 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::MIN($colData);
} // function DMIN()
/**
* 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;
}
// 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_MathTrig::PRODUCT($colData);
} // function DPRODUCT()
/**
* 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;
}
// 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::STDEV($colData);
} // function DSTDEV()
/**
* 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;
}
// 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::STDEVP($colData);
} // function DSTDEVP()
/**
* 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;
}
// 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_MathTrig::SUM($colData);
} // function DSUM()
/**
* 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;
}
// 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::VARFunc($colData);
} // function DVAR()
/**
* 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;
}
// 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::VARP($colData);
} // function DVARP()
} // class PHPExcel_Calculation_Database

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Calculation_Exception
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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;
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Calculation_ExceptionHandler
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,614 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/*
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
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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);
} else 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_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;
} else 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_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);
} else if ($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;
}
}
}

View File

@ -0,0 +1,176 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/*
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
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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;
}
}

View File

@ -0,0 +1,149 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Calculation_Function
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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;
}
}

View File

@ -0,0 +1,725 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 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 - 2014 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 #NULL!
*/
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 = str_replace('"', '""', $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 1.8.1, 2015-04-30';
} // 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' :
// Errors
if ((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 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;
} // 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()
}
//
// 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;
}
}

View File

@ -0,0 +1,288 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 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');
}
/**
* PHPExcel_Calculation_Logical
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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;
} // function TRUE()
/**
* FALSE
*
* Returns the boolean FALSE.
*
* Excel Function:
* =FALSE()
*
* @access public
* @category Logical Functions
* @return boolean False
*/
public static function FALSE() {
return FALSE;
} // function 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;
} // function LOGICAL_AND()
/**
* 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;
} // function LOGICAL_OR()
/**
* 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;
} // function NOT()
/**
* 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;
} // function STATEMENT_IF()
/**
* 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);
} // function IFERROR()
} // class PHPExcel_Calculation_Logical

View File

@ -0,0 +1,876 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 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');
}
/**
* PHPExcel_Calculation_LookupRef
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
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;
}
} // function CELL_ADDRESS()
/**
* 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);
}
}
} // function COLUMN()
/**
* 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();
}
$x = array_keys($cellAddress);
$x = array_shift($x);
$isMatrix = (is_numeric($x));
list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress);
if ($isMatrix) {
return $rows;
} else {
return $columns;
}
} // function 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);
}
}
} // function ROW()
/**
* 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();
}
$i = array_keys($cellAddress);
$isMatrix = (is_numeric(array_shift($i)));
list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress);
if ($isMatrix) {
return $columns;
} else {
return $rows;
}
} // function 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);
return $displayName;
} // function HYPERLINK()
/**
* 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);
} // function INDIRECT()
/**
* 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);
} // function OFFSET()
/**
* 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];
}
} // function CHOOSE()
/**
* 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
// **
// loop on the cells
// var_dump($lookup_array);
// echo '<br />';
foreach($lookup_array as $i => $lookupArrayValue) {
if (($match_type == 0) && ($lookupArrayValue == $lookup_value)) {
// exact match
return ++$i;
} elseif (($match_type == -1) && ($lookupArrayValue <= $lookup_value)) {
// echo '$i = '.$i.' => ';
// var_dump($lookupArrayValue);
// echo '<br />';
// echo 'Keyset = ';
// var_dump($keySet);
// echo '<br />';
$i = array_search($i,$keySet);
// echo '$i='.$i.'<br />';
// if match_type is -1 <=> find the smallest value that is greater than or equal to lookup_value
if ($i < 1){
// 1st cell was allready 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)) {
// echo '$i = '.$i.' => ';
// var_dump($lookupArrayValue);
// echo '<br />';
// echo 'Keyset = ';
// var_dump($keySet);
// echo '<br />';
$i = array_search($i,$keySet);
// echo '$i='.$i.'<br />';
// if match_type is 1 <=> find the largest value that is less than or equal to lookup_value
if ($i < 1){
// 1st cell was allready 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();
} // function MATCH()
/**
* 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];
} // function INDEX()
/**
* 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;
} // function TRANSPOSE()
private static function _vlookupSort($a,$b) {
$f = array_keys($a);
$firstColumn = array_shift($f);
if (strtolower($a[$firstColumn]) == strtolower($b[$firstColumn])) {
return 0;
}
return (strtolower($a[$firstColumn]) < strtolower($b[$firstColumn])) ? -1 : 1;
} // function _vlookupSort()
/**
* 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();
} // function VLOOKUP()
/**
* 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();
} // function HLOOKUP()
/**
* 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);
} // function LOOKUP()
} // class PHPExcel_Calculation_LookupRef

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,630 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2014 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 - 2014 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');
}
/**
* PHPExcel_Calculation_TextData
*
* @category PHPExcel
* @package PHPExcel_Calculation
* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Calculation_TextData {
private static $_invalidChars = Null;
private static function _uniord($c) {
if (ord($c{0}) >=0 && ord($c{0}) <= 127)
return ord($c{0});
if (ord($c{0}) >= 192 && ord($c{0}) <= 223)
return (ord($c{0})-192)*64 + (ord($c{1})-128);
if (ord($c{0}) >= 224 && ord($c{0}) <= 239)
return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128);
if (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);
if (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);
if (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);
if (ord($c{0}) >= 254 && ord($c{0}) <= 255) //error
return PHPExcel_Calculation_Functions::VALUE();
return 0;
} // function _uniord()
/**
* 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;
} // function TRIMNONPRINTABLE()
/**
* 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;
} // function TRIMSPACES()
/**
* 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::_uniord($character);
} else {
if (strlen($characters) > 0) { $character = substr($characters, 0, 1); }
return ord($character);
}
} // function ASCIICODE()
/**
* CONCATENATE
*
* @return string
*/
public static function CONCATENATE() {
// Return value
$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
return $returnValue;
} // function CONCATENATE()
/**
* 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);
} // function DOLLAR()
/**
* 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();
} // function SEARCHSENSITIVE()
/**
* 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();
} // function SEARCHINSENSITIVE()
/**
* 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;
} // function FIXEDFORMAT()
/**
* 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);
}
} // function LEFT()
/**
* 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);
}
} // function MID()
/**
* 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);
}
} // function RIGHT()
/**
* 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);
}
} // function STRINGLENGTH()
/**
* 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);
} // function LOWERCASE()
/**
* 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);
} // function UPPERCASE()
/**
* 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);
} // function PROPERCASE()
/**
* 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;
} // function REPLACE()
/**
* 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;
} // function SUBSTITUTE()
/**
* 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;
} // function RETURNSTRING()
/**
* 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);
} // function TEXTFORMAT()
/**
* 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;
}
}

View File

@ -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