Functions.php 21 KB

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