Functions.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2014 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Calculation
  23. * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version 1.8.0, 2014-03-02
  26. */
  27. /** PHPExcel root directory */
  28. if (!defined('PHPEXCEL_ROOT')) {
  29. /**
  30. * @ignore
  31. */
  32. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  33. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  34. }
  35. /** MAX_VALUE */
  36. define('MAX_VALUE', 1.2e308);
  37. /** 2 / PI */
  38. define('M_2DIVPI', 0.63661977236758134307553505349006);
  39. /** MAX_ITERATIONS */
  40. define('MAX_ITERATIONS', 256);
  41. /** PRECISION */
  42. define('PRECISION', 8.88E-016);
  43. /**
  44. * PHPExcel_Calculation_Functions
  45. *
  46. * @category PHPExcel
  47. * @package PHPExcel_Calculation
  48. * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
  49. */
  50. class PHPExcel_Calculation_Functions {
  51. /** constants */
  52. const COMPATIBILITY_EXCEL = 'Excel';
  53. const COMPATIBILITY_GNUMERIC = 'Gnumeric';
  54. const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc';
  55. const RETURNDATE_PHP_NUMERIC = 'P';
  56. const RETURNDATE_PHP_OBJECT = 'O';
  57. const RETURNDATE_EXCEL = 'E';
  58. /**
  59. * Compatibility mode to use for error checking and responses
  60. *
  61. * @access private
  62. * @var string
  63. */
  64. protected static $compatibilityMode = self::COMPATIBILITY_EXCEL;
  65. /**
  66. * Data Type to use when returning date values
  67. *
  68. * @access private
  69. * @var string
  70. */
  71. protected static $ReturnDateType = self::RETURNDATE_EXCEL;
  72. /**
  73. * List of error codes
  74. *
  75. * @access private
  76. * @var array
  77. */
  78. protected static $_errorCodes = array( 'null' => '#NULL!',
  79. 'divisionbyzero' => '#DIV/0!',
  80. 'value' => '#VALUE!',
  81. 'reference' => '#REF!',
  82. 'name' => '#NAME?',
  83. 'num' => '#NUM!',
  84. 'na' => '#N/A',
  85. 'gettingdata' => '#GETTING_DATA'
  86. );
  87. /**
  88. * Set the Compatibility Mode
  89. *
  90. * @access public
  91. * @category Function Configuration
  92. * @param string $compatibilityMode Compatibility Mode
  93. * Permitted values are:
  94. * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel'
  95. * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric'
  96. * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc'
  97. * @return boolean (Success or Failure)
  98. */
  99. public static function setCompatibilityMode($compatibilityMode) {
  100. if (($compatibilityMode == self::COMPATIBILITY_EXCEL) ||
  101. ($compatibilityMode == self::COMPATIBILITY_GNUMERIC) ||
  102. ($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  103. self::$compatibilityMode = $compatibilityMode;
  104. return True;
  105. }
  106. return False;
  107. } // function setCompatibilityMode()
  108. /**
  109. * Return the current Compatibility Mode
  110. *
  111. * @access public
  112. * @category Function Configuration
  113. * @return string Compatibility Mode
  114. * Possible Return values are:
  115. * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel'
  116. * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric'
  117. * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc'
  118. */
  119. public static function getCompatibilityMode() {
  120. return self::$compatibilityMode;
  121. } // function getCompatibilityMode()
  122. /**
  123. * Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object)
  124. *
  125. * @access public
  126. * @category Function Configuration
  127. * @param string $returnDateType Return Date Format
  128. * Permitted values are:
  129. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P'
  130. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O'
  131. * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E'
  132. * @return boolean Success or failure
  133. */
  134. public static function setReturnDateType($returnDateType) {
  135. if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) ||
  136. ($returnDateType == self::RETURNDATE_PHP_OBJECT) ||
  137. ($returnDateType == self::RETURNDATE_EXCEL)) {
  138. self::$ReturnDateType = $returnDateType;
  139. return True;
  140. }
  141. return False;
  142. } // function setReturnDateType()
  143. /**
  144. * Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object)
  145. *
  146. * @access public
  147. * @category Function Configuration
  148. * @return string Return Date Format
  149. * Possible Return values are:
  150. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P'
  151. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O'
  152. * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E'
  153. */
  154. public static function getReturnDateType() {
  155. return self::$ReturnDateType;
  156. } // function getReturnDateType()
  157. /**
  158. * DUMMY
  159. *
  160. * @access public
  161. * @category Error Returns
  162. * @return string #Not Yet Implemented
  163. */
  164. public static function DUMMY() {
  165. return '#Not Yet Implemented';
  166. } // function DUMMY()
  167. /**
  168. * DIV0
  169. *
  170. * @access public
  171. * @category Error Returns
  172. * @return string #Not Yet Implemented
  173. */
  174. public static function DIV0() {
  175. return self::$_errorCodes['divisionbyzero'];
  176. } // function DIV0()
  177. /**
  178. * NA
  179. *
  180. * Excel Function:
  181. * =NA()
  182. *
  183. * Returns the error value #N/A
  184. * #N/A is the error value that means "no value is available."
  185. *
  186. * @access public
  187. * @category Logical Functions
  188. * @return string #N/A!
  189. */
  190. public static function NA() {
  191. return self::$_errorCodes['na'];
  192. } // function NA()
  193. /**
  194. * NaN
  195. *
  196. * Returns the error value #NUM!
  197. *
  198. * @access public
  199. * @category Error Returns
  200. * @return string #NUM!
  201. */
  202. public static function NaN() {
  203. return self::$_errorCodes['num'];
  204. } // function NaN()
  205. /**
  206. * NAME
  207. *
  208. * Returns the error value #NAME?
  209. *
  210. * @access public
  211. * @category Error Returns
  212. * @return string #NAME?
  213. */
  214. public static function NAME() {
  215. return self::$_errorCodes['name'];
  216. } // function NAME()
  217. /**
  218. * REF
  219. *
  220. * Returns the error value #REF!
  221. *
  222. * @access public
  223. * @category Error Returns
  224. * @return string #REF!
  225. */
  226. public static function REF() {
  227. return self::$_errorCodes['reference'];
  228. } // function REF()
  229. /**
  230. * NULL
  231. *
  232. * Returns the error value #NULL!
  233. *
  234. * @access public
  235. * @category Error Returns
  236. * @return string #NULL!
  237. */
  238. public static function NULL() {
  239. return self::$_errorCodes['null'];
  240. } // function NULL()
  241. /**
  242. * VALUE
  243. *
  244. * Returns the error value #VALUE!
  245. *
  246. * @access public
  247. * @category Error Returns
  248. * @return string #VALUE!
  249. */
  250. public static function VALUE() {
  251. return self::$_errorCodes['value'];
  252. } // function VALUE()
  253. public static function isMatrixValue($idx) {
  254. return ((substr_count($idx,'.') <= 1) || (preg_match('/\.[A-Z]/',$idx) > 0));
  255. }
  256. public static function isValue($idx) {
  257. return (substr_count($idx,'.') == 0);
  258. }
  259. public static function isCellValue($idx) {
  260. return (substr_count($idx,'.') > 1);
  261. }
  262. public static function _ifCondition($condition) {
  263. $condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition);
  264. if (!isset($condition{0}))
  265. $condition = '=""';
  266. if (!in_array($condition{0},array('>', '<', '='))) {
  267. if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); }
  268. return '='.$condition;
  269. } else {
  270. preg_match('/([<>=]+)(.*)/',$condition,$matches);
  271. list(,$operator,$operand) = $matches;
  272. if (!is_numeric($operand)) {
  273. $operand = str_replace('"', '""', $operand);
  274. $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand));
  275. }
  276. return $operator.$operand;
  277. }
  278. } // function _ifCondition()
  279. /**
  280. * ERROR_TYPE
  281. *
  282. * @param mixed $value Value to check
  283. * @return boolean
  284. */
  285. public static function ERROR_TYPE($value = '') {
  286. $value = self::flattenSingleValue($value);
  287. $i = 1;
  288. foreach(self::$_errorCodes as $errorCode) {
  289. if ($value === $errorCode) {
  290. return $i;
  291. }
  292. ++$i;
  293. }
  294. return self::NA();
  295. } // function ERROR_TYPE()
  296. /**
  297. * IS_BLANK
  298. *
  299. * @param mixed $value Value to check
  300. * @return boolean
  301. */
  302. public static function IS_BLANK($value = NULL) {
  303. if (!is_null($value)) {
  304. $value = self::flattenSingleValue($value);
  305. }
  306. return is_null($value);
  307. } // function IS_BLANK()
  308. /**
  309. * IS_ERR
  310. *
  311. * @param mixed $value Value to check
  312. * @return boolean
  313. */
  314. public static function IS_ERR($value = '') {
  315. $value = self::flattenSingleValue($value);
  316. return self::IS_ERROR($value) && (!self::IS_NA($value));
  317. } // function IS_ERR()
  318. /**
  319. * IS_ERROR
  320. *
  321. * @param mixed $value Value to check
  322. * @return boolean
  323. */
  324. public static function IS_ERROR($value = '') {
  325. $value = self::flattenSingleValue($value);
  326. if (!is_string($value))
  327. return false;
  328. return in_array($value, array_values(self::$_errorCodes));
  329. } // function IS_ERROR()
  330. /**
  331. * IS_NA
  332. *
  333. * @param mixed $value Value to check
  334. * @return boolean
  335. */
  336. public static function IS_NA($value = '') {
  337. $value = self::flattenSingleValue($value);
  338. return ($value === self::NA());
  339. } // function IS_NA()
  340. /**
  341. * IS_EVEN
  342. *
  343. * @param mixed $value Value to check
  344. * @return boolean
  345. */
  346. public static function IS_EVEN($value = NULL) {
  347. $value = self::flattenSingleValue($value);
  348. if ($value === NULL)
  349. return self::NAME();
  350. if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value))))
  351. return self::VALUE();
  352. return ($value % 2 == 0);
  353. } // function IS_EVEN()
  354. /**
  355. * IS_ODD
  356. *
  357. * @param mixed $value Value to check
  358. * @return boolean
  359. */
  360. public static function IS_ODD($value = NULL) {
  361. $value = self::flattenSingleValue($value);
  362. if ($value === NULL)
  363. return self::NAME();
  364. if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value))))
  365. return self::VALUE();
  366. return (abs($value) % 2 == 1);
  367. } // function IS_ODD()
  368. /**
  369. * IS_NUMBER
  370. *
  371. * @param mixed $value Value to check
  372. * @return boolean
  373. */
  374. public static function IS_NUMBER($value = NULL) {
  375. $value = self::flattenSingleValue($value);
  376. if (is_string($value)) {
  377. return False;
  378. }
  379. return is_numeric($value);
  380. } // function IS_NUMBER()
  381. /**
  382. * IS_LOGICAL
  383. *
  384. * @param mixed $value Value to check
  385. * @return boolean
  386. */
  387. public static function IS_LOGICAL($value = NULL) {
  388. $value = self::flattenSingleValue($value);
  389. return is_bool($value);
  390. } // function IS_LOGICAL()
  391. /**
  392. * IS_TEXT
  393. *
  394. * @param mixed $value Value to check
  395. * @return boolean
  396. */
  397. public static function IS_TEXT($value = NULL) {
  398. $value = self::flattenSingleValue($value);
  399. return (is_string($value) && !self::IS_ERROR($value));
  400. } // function IS_TEXT()
  401. /**
  402. * IS_NONTEXT
  403. *
  404. * @param mixed $value Value to check
  405. * @return boolean
  406. */
  407. public static function IS_NONTEXT($value = NULL) {
  408. return !self::IS_TEXT($value);
  409. } // function IS_NONTEXT()
  410. /**
  411. * VERSION
  412. *
  413. * @return string Version information
  414. */
  415. public static function VERSION() {
  416. return 'PHPExcel 1.8.0, 2014-03-02';
  417. } // function VERSION()
  418. /**
  419. * N
  420. *
  421. * Returns a value converted to a number
  422. *
  423. * @param value The value you want converted
  424. * @return number N converts values listed in the following table
  425. * If value is or refers to N returns
  426. * A number That number
  427. * A date The serial number of that date
  428. * TRUE 1
  429. * FALSE 0
  430. * An error value The error value
  431. * Anything else 0
  432. */
  433. public static function N($value = NULL) {
  434. while (is_array($value)) {
  435. $value = array_shift($value);
  436. }
  437. switch (gettype($value)) {
  438. case 'double' :
  439. case 'float' :
  440. case 'integer' :
  441. return $value;
  442. break;
  443. case 'boolean' :
  444. return (integer) $value;
  445. break;
  446. case 'string' :
  447. // Errors
  448. if ((strlen($value) > 0) && ($value{0} == '#')) {
  449. return $value;
  450. }
  451. break;
  452. }
  453. return 0;
  454. } // function N()
  455. /**
  456. * TYPE
  457. *
  458. * Returns a number that identifies the type of a value
  459. *
  460. * @param value The value you want tested
  461. * @return number N converts values listed in the following table
  462. * If value is or refers to N returns
  463. * A number 1
  464. * Text 2
  465. * Logical Value 4
  466. * An error value 16
  467. * Array or Matrix 64
  468. */
  469. public static function TYPE($value = NULL) {
  470. $value = self::flattenArrayIndexed($value);
  471. if (is_array($value) && (count($value) > 1)) {
  472. $a = array_keys($value);
  473. $a = array_pop($a);
  474. // Range of cells is an error
  475. if (self::isCellValue($a)) {
  476. return 16;
  477. // Test for Matrix
  478. } elseif (self::isMatrixValue($a)) {
  479. return 64;
  480. }
  481. } elseif(empty($value)) {
  482. // Empty Cell
  483. return 1;
  484. }
  485. $value = self::flattenSingleValue($value);
  486. if (($value === NULL) || (is_float($value)) || (is_int($value))) {
  487. return 1;
  488. } elseif(is_bool($value)) {
  489. return 4;
  490. } elseif(is_array($value)) {
  491. return 64;
  492. break;
  493. } elseif(is_string($value)) {
  494. // Errors
  495. if ((strlen($value) > 0) && ($value{0} == '#')) {
  496. return 16;
  497. }
  498. return 2;
  499. }
  500. return 0;
  501. } // function TYPE()
  502. /**
  503. * Convert a multi-dimensional array to a simple 1-dimensional array
  504. *
  505. * @param array $array Array to be flattened
  506. * @return array Flattened array
  507. */
  508. public static function flattenArray($array) {
  509. if (!is_array($array)) {
  510. return (array) $array;
  511. }
  512. $arrayValues = array();
  513. foreach ($array as $value) {
  514. if (is_array($value)) {
  515. foreach ($value as $val) {
  516. if (is_array($val)) {
  517. foreach ($val as $v) {
  518. $arrayValues[] = $v;
  519. }
  520. } else {
  521. $arrayValues[] = $val;
  522. }
  523. }
  524. } else {
  525. $arrayValues[] = $value;
  526. }
  527. }
  528. return $arrayValues;
  529. } // function flattenArray()
  530. /**
  531. * Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing
  532. *
  533. * @param array $array Array to be flattened
  534. * @return array Flattened array
  535. */
  536. public static function flattenArrayIndexed($array) {
  537. if (!is_array($array)) {
  538. return (array) $array;
  539. }
  540. $arrayValues = array();
  541. foreach ($array as $k1 => $value) {
  542. if (is_array($value)) {
  543. foreach ($value as $k2 => $val) {
  544. if (is_array($val)) {
  545. foreach ($val as $k3 => $v) {
  546. $arrayValues[$k1.'.'.$k2.'.'.$k3] = $v;
  547. }
  548. } else {
  549. $arrayValues[$k1.'.'.$k2] = $val;
  550. }
  551. }
  552. } else {
  553. $arrayValues[$k1] = $value;
  554. }
  555. }
  556. return $arrayValues;
  557. } // function flattenArrayIndexed()
  558. /**
  559. * Convert an array to a single scalar value by extracting the first element
  560. *
  561. * @param mixed $value Array or scalar value
  562. * @return mixed
  563. */
  564. public static function flattenSingleValue($value = '') {
  565. while (is_array($value)) {
  566. $value = array_pop($value);
  567. }
  568. return $value;
  569. } // function flattenSingleValue()
  570. } // class PHPExcel_Calculation_Functions
  571. //
  572. // There are a few mathematical functions that aren't available on all versions of PHP for all platforms
  573. // These functions aren't available in Windows implementations of PHP prior to version 5.3.0
  574. // So we test if they do exist for this version of PHP/operating platform; and if not we create them
  575. //
  576. if (!function_exists('acosh')) {
  577. function acosh($x) {
  578. return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2));
  579. } // function acosh()
  580. }
  581. if (!function_exists('asinh')) {
  582. function asinh($x) {
  583. return log($x + sqrt(1 + $x * $x));
  584. } // function asinh()
  585. }
  586. if (!function_exists('atanh')) {
  587. function atanh($x) {
  588. return (log(1 + $x) - log(1 - $x)) / 2;
  589. } // function atanh()
  590. }
  591. //
  592. // Strangely, PHP doesn't have a mb_str_replace multibyte function
  593. // As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set
  594. //
  595. if ((!function_exists('mb_str_replace')) &&
  596. (function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) {
  597. function mb_str_replace($search, $replace, $subject) {
  598. if(is_array($subject)) {
  599. $ret = array();
  600. foreach($subject as $key => $val) {
  601. $ret[$key] = mb_str_replace($search, $replace, $val);
  602. }
  603. return $ret;
  604. }
  605. foreach((array) $search as $key => $s) {
  606. if($s == '') {
  607. continue;
  608. }
  609. $r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : '');
  610. $pos = mb_strpos($subject, $s, 0, 'UTF-8');
  611. while($pos !== false) {
  612. $subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8');
  613. $pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8');
  614. }
  615. }
  616. return $subject;
  617. }
  618. }