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

1459 lines
47 KiB

  1. <?php
  2. /** PHPExcel root directory */
  3. if (!defined('PHPEXCEL_ROOT')) {
  4. /**
  5. * @ignore
  6. */
  7. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  8. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  9. }
  10. /**
  11. * PHPExcel_Calculation_MathTrig
  12. *
  13. * Copyright (c) 2006 - 2015 PHPExcel
  14. *
  15. * This library is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU Lesser General Public
  17. * License as published by the Free Software Foundation; either
  18. * version 2.1 of the License, or (at your option) any later version.
  19. *
  20. * This library is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  23. * Lesser General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU Lesser General Public
  26. * License along with this library; if not, write to the Free Software
  27. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. *
  29. * @category PHPExcel
  30. * @package PHPExcel_Calculation
  31. * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  32. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  33. * @version ##VERSION##, ##DATE##
  34. */
  35. class PHPExcel_Calculation_MathTrig
  36. {
  37. //
  38. // Private method to return an array of the factors of the input value
  39. //
  40. private static function factors($value)
  41. {
  42. $startVal = floor(sqrt($value));
  43. $factorArray = array();
  44. for ($i = $startVal; $i > 1; --$i) {
  45. if (($value % $i) == 0) {
  46. $factorArray = array_merge($factorArray, self::factors($value / $i));
  47. $factorArray = array_merge($factorArray, self::factors($i));
  48. if ($i <= sqrt($value)) {
  49. break;
  50. }
  51. }
  52. }
  53. if (!empty($factorArray)) {
  54. rsort($factorArray);
  55. return $factorArray;
  56. } else {
  57. return array((integer) $value);
  58. }
  59. }
  60. private static function romanCut($num, $n)
  61. {
  62. return ($num - ($num % $n ) ) / $n;
  63. }
  64. /**
  65. * ATAN2
  66. *
  67. * This function calculates the arc tangent of the two variables x and y. It is similar to
  68. * calculating the arc tangent of y ÷ x, except that the signs of both arguments are used
  69. * to determine the quadrant of the result.
  70. * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a
  71. * point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between
  72. * -pi and pi, excluding -pi.
  73. *
  74. * Note that the Excel ATAN2() function accepts its arguments in the reverse order to the standard
  75. * PHP atan2() function, so we need to reverse them here before calling the PHP atan() function.
  76. *
  77. * Excel Function:
  78. * ATAN2(xCoordinate,yCoordinate)
  79. *
  80. * @access public
  81. * @category Mathematical and Trigonometric Functions
  82. * @param float $xCoordinate The x-coordinate of the point.
  83. * @param float $yCoordinate The y-coordinate of the point.
  84. * @return float The inverse tangent of the specified x- and y-coordinates.
  85. */
  86. public static function ATAN2($xCoordinate = null, $yCoordinate = null)
  87. {
  88. $xCoordinate = PHPExcel_Calculation_Functions::flattenSingleValue($xCoordinate);
  89. $yCoordinate = PHPExcel_Calculation_Functions::flattenSingleValue($yCoordinate);
  90. $xCoordinate = ($xCoordinate !== null) ? $xCoordinate : 0.0;
  91. $yCoordinate = ($yCoordinate !== null) ? $yCoordinate : 0.0;
  92. if (((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) &&
  93. ((is_numeric($yCoordinate))) || (is_bool($yCoordinate))) {
  94. $xCoordinate = (float) $xCoordinate;
  95. $yCoordinate = (float) $yCoordinate;
  96. if (($xCoordinate == 0) && ($yCoordinate == 0)) {
  97. return PHPExcel_Calculation_Functions::DIV0();
  98. }
  99. return atan2($yCoordinate, $xCoordinate);
  100. }
  101. return PHPExcel_Calculation_Functions::VALUE();
  102. }
  103. /**
  104. * CEILING
  105. *
  106. * Returns number rounded up, away from zero, to the nearest multiple of significance.
  107. * For example, if you want to avoid using pennies in your prices and your product is
  108. * priced at $4.42, use the formula =CEILING(4.42,0.05) to round prices up to the
  109. * nearest nickel.
  110. *
  111. * Excel Function:
  112. * CEILING(number[,significance])
  113. *
  114. * @access public
  115. * @category Mathematical and Trigonometric Functions
  116. * @param float $number The number you want to round.
  117. * @param float $significance The multiple to which you want to round.
  118. * @return float Rounded Number
  119. */
  120. public static function CEILING($number, $significance = null)
  121. {
  122. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  123. $significance = PHPExcel_Calculation_Functions::flattenSingleValue($significance);
  124. if ((is_null($significance)) &&
  125. (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) {
  126. $significance = $number / abs($number);
  127. }
  128. if ((is_numeric($number)) && (is_numeric($significance))) {
  129. if (($number == 0.0 ) || ($significance == 0.0)) {
  130. return 0.0;
  131. } elseif (self::SIGN($number) == self::SIGN($significance)) {
  132. return ceil($number / $significance) * $significance;
  133. } else {
  134. return PHPExcel_Calculation_Functions::NaN();
  135. }
  136. }
  137. return PHPExcel_Calculation_Functions::VALUE();
  138. }
  139. /**
  140. * COMBIN
  141. *
  142. * Returns the number of combinations for a given number of items. Use COMBIN to
  143. * determine the total possible number of groups for a given number of items.
  144. *
  145. * Excel Function:
  146. * COMBIN(numObjs,numInSet)
  147. *
  148. * @access public
  149. * @category Mathematical and Trigonometric Functions
  150. * @param int $numObjs Number of different objects
  151. * @param int $numInSet Number of objects in each combination
  152. * @return int Number of combinations
  153. */
  154. public static function COMBIN($numObjs, $numInSet)
  155. {
  156. $numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs);
  157. $numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet);
  158. if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
  159. if ($numObjs < $numInSet) {
  160. return PHPExcel_Calculation_Functions::NaN();
  161. } elseif ($numInSet < 0) {
  162. return PHPExcel_Calculation_Functions::NaN();
  163. }
  164. return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet);
  165. }
  166. return PHPExcel_Calculation_Functions::VALUE();
  167. }
  168. /**
  169. * EVEN
  170. *
  171. * Returns number rounded up to the nearest even integer.
  172. * You can use this function for processing items that come in twos. For example,
  173. * a packing crate accepts rows of one or two items. The crate is full when
  174. * the number of items, rounded up to the nearest two, matches the crate's
  175. * capacity.
  176. *
  177. * Excel Function:
  178. * EVEN(number)
  179. *
  180. * @access public
  181. * @category Mathematical and Trigonometric Functions
  182. * @param float $number Number to round
  183. * @return int Rounded Number
  184. */
  185. public static function EVEN($number)
  186. {
  187. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  188. if (is_null($number)) {
  189. return 0;
  190. } elseif (is_bool($number)) {
  191. $number = (int) $number;
  192. }
  193. if (is_numeric($number)) {
  194. $significance = 2 * self::SIGN($number);
  195. return (int) self::CEILING($number, $significance);
  196. }
  197. return PHPExcel_Calculation_Functions::VALUE();
  198. }
  199. /**
  200. * FACT
  201. *
  202. * Returns the factorial of a number.
  203. * The factorial of a number is equal to 1*2*3*...* number.
  204. *
  205. * Excel Function:
  206. * FACT(factVal)
  207. *
  208. * @access public
  209. * @category Mathematical and Trigonometric Functions
  210. * @param float $factVal Factorial Value
  211. * @return int Factorial
  212. */
  213. public static function FACT($factVal)
  214. {
  215. $factVal = PHPExcel_Calculation_Functions::flattenSingleValue($factVal);
  216. if (is_numeric($factVal)) {
  217. if ($factVal < 0) {
  218. return PHPExcel_Calculation_Functions::NaN();
  219. }
  220. $factLoop = floor($factVal);
  221. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  222. if ($factVal > $factLoop) {
  223. return PHPExcel_Calculation_Functions::NaN();
  224. }
  225. }
  226. $factorial = 1;
  227. while ($factLoop > 1) {
  228. $factorial *= $factLoop--;
  229. }
  230. return $factorial ;
  231. }
  232. return PHPExcel_Calculation_Functions::VALUE();
  233. }
  234. /**
  235. * FACTDOUBLE
  236. *
  237. * Returns the double factorial of a number.
  238. *
  239. * Excel Function:
  240. * FACTDOUBLE(factVal)
  241. *
  242. * @access public
  243. * @category Mathematical and Trigonometric Functions
  244. * @param float $factVal Factorial Value
  245. * @return int Double Factorial
  246. */
  247. public static function FACTDOUBLE($factVal)
  248. {
  249. $factLoop = PHPExcel_Calculation_Functions::flattenSingleValue($factVal);
  250. if (is_numeric($factLoop)) {
  251. $factLoop = floor($factLoop);
  252. if ($factVal < 0) {
  253. return PHPExcel_Calculation_Functions::NaN();
  254. }
  255. $factorial = 1;
  256. while ($factLoop > 1) {
  257. $factorial *= $factLoop--;
  258. --$factLoop;
  259. }
  260. return $factorial ;
  261. }
  262. return PHPExcel_Calculation_Functions::VALUE();
  263. }
  264. /**
  265. * FLOOR
  266. *
  267. * Rounds number down, toward zero, to the nearest multiple of significance.
  268. *
  269. * Excel Function:
  270. * FLOOR(number[,significance])
  271. *
  272. * @access public
  273. * @category Mathematical and Trigonometric Functions
  274. * @param float $number Number to round
  275. * @param float $significance Significance
  276. * @return float Rounded Number
  277. */
  278. public static function FLOOR($number, $significance = null)
  279. {
  280. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  281. $significance = PHPExcel_Calculation_Functions::flattenSingleValue($significance);
  282. if ((is_null($significance)) &&
  283. (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) {
  284. $significance = $number/abs($number);
  285. }
  286. if ((is_numeric($number)) && (is_numeric($significance))) {
  287. if ($significance == 0.0) {
  288. return PHPExcel_Calculation_Functions::DIV0();
  289. } elseif ($number == 0.0) {
  290. return 0.0;
  291. } elseif (self::SIGN($number) == self::SIGN($significance)) {
  292. return floor($number / $significance) * $significance;
  293. } else {
  294. return PHPExcel_Calculation_Functions::NaN();
  295. }
  296. }
  297. return PHPExcel_Calculation_Functions::VALUE();
  298. }
  299. /**
  300. * GCD
  301. *
  302. * Returns the greatest common divisor of a series of numbers.
  303. * The greatest common divisor is the largest integer that divides both
  304. * number1 and number2 without a remainder.
  305. *
  306. * Excel Function:
  307. * GCD(number1[,number2[, ...]])
  308. *
  309. * @access public
  310. * @category Mathematical and Trigonometric Functions
  311. * @param mixed $arg,... Data values
  312. * @return integer Greatest Common Divisor
  313. */
  314. public static function GCD()
  315. {
  316. $returnValue = 1;
  317. $allValuesFactors = array();
  318. // Loop through arguments
  319. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $value) {
  320. if (!is_numeric($value)) {
  321. return PHPExcel_Calculation_Functions::VALUE();
  322. } elseif ($value == 0) {
  323. continue;
  324. } elseif ($value < 0) {
  325. return PHPExcel_Calculation_Functions::NaN();
  326. }
  327. $myFactors = self::factors($value);
  328. $myCountedFactors = array_count_values($myFactors);
  329. $allValuesFactors[] = $myCountedFactors;
  330. }
  331. $allValuesCount = count($allValuesFactors);
  332. if ($allValuesCount == 0) {
  333. return 0;
  334. }
  335. $mergedArray = $allValuesFactors[0];
  336. for ($i=1; $i < $allValuesCount; ++$i) {
  337. $mergedArray = array_intersect_key($mergedArray, $allValuesFactors[$i]);
  338. }
  339. $mergedArrayValues = count($mergedArray);
  340. if ($mergedArrayValues == 0) {
  341. return $returnValue;
  342. } elseif ($mergedArrayValues > 1) {
  343. foreach ($mergedArray as $mergedKey => $mergedValue) {
  344. foreach ($allValuesFactors as $highestPowerTest) {
  345. foreach ($highestPowerTest as $testKey => $testValue) {
  346. if (($testKey == $mergedKey) && ($testValue < $mergedValue)) {
  347. $mergedArray[$mergedKey] = $testValue;
  348. $mergedValue = $testValue;
  349. }
  350. }
  351. }
  352. }
  353. $returnValue = 1;
  354. foreach ($mergedArray as $key => $value) {
  355. $returnValue *= pow($key, $value);
  356. }
  357. return $returnValue;
  358. } else {
  359. $keys = array_keys($mergedArray);
  360. $key = $keys[0];
  361. $value = $mergedArray[$key];
  362. foreach ($allValuesFactors as $testValue) {
  363. foreach ($testValue as $mergedKey => $mergedValue) {
  364. if (($mergedKey == $key) && ($mergedValue < $value)) {
  365. $value = $mergedValue;
  366. }
  367. }
  368. }
  369. return pow($key, $value);
  370. }
  371. }
  372. /**
  373. * INT
  374. *
  375. * Casts a floating point value to an integer
  376. *
  377. * Excel Function:
  378. * INT(number)
  379. *
  380. * @access public
  381. * @category Mathematical and Trigonometric Functions
  382. * @param float $number Number to cast to an integer
  383. * @return integer Integer value
  384. */
  385. public static function INT($number)
  386. {
  387. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  388. if (is_null($number)) {
  389. return 0;
  390. } elseif (is_bool($number)) {
  391. return (int) $number;
  392. }
  393. if (is_numeric($number)) {
  394. return (int) floor($number);
  395. }
  396. return PHPExcel_Calculation_Functions::VALUE();
  397. }
  398. /**
  399. * LCM
  400. *
  401. * Returns the lowest common multiplier of a series of numbers
  402. * The least common multiple is the smallest positive integer that is a multiple
  403. * of all integer arguments number1, number2, and so on. Use LCM to add fractions
  404. * with different denominators.
  405. *
  406. * Excel Function:
  407. * LCM(number1[,number2[, ...]])
  408. *
  409. * @access public
  410. * @category Mathematical and Trigonometric Functions
  411. * @param mixed $arg,... Data values
  412. * @return int Lowest Common Multiplier
  413. */
  414. public static function LCM()
  415. {
  416. $returnValue = 1;
  417. $allPoweredFactors = array();
  418. // Loop through arguments
  419. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $value) {
  420. if (!is_numeric($value)) {
  421. return PHPExcel_Calculation_Functions::VALUE();
  422. }
  423. if ($value == 0) {
  424. return 0;
  425. } elseif ($value < 0) {
  426. return PHPExcel_Calculation_Functions::NaN();
  427. }
  428. $myFactors = self::factors(floor($value));
  429. $myCountedFactors = array_count_values($myFactors);
  430. $myPoweredFactors = array();
  431. foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
  432. $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor, $myCountedPower);
  433. }
  434. foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
  435. if (array_key_exists($myPoweredValue, $allPoweredFactors)) {
  436. if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
  437. $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
  438. }
  439. } else {
  440. $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
  441. }
  442. }
  443. }
  444. foreach ($allPoweredFactors as $allPoweredFactor) {
  445. $returnValue *= (integer) $allPoweredFactor;
  446. }
  447. return $returnValue;
  448. }
  449. /**
  450. * LOG_BASE
  451. *
  452. * Returns the logarithm of a number to a specified base. The default base is 10.
  453. *
  454. * Excel Function:
  455. * LOG(number[,base])
  456. *
  457. * @access public
  458. * @category Mathematical and Trigonometric Functions
  459. * @param float $number The positive real number for which you want the logarithm
  460. * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10.
  461. * @return float
  462. */
  463. public static function LOG_BASE($number = null, $base = 10)
  464. {
  465. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  466. $base = (is_null($base)) ? 10 : (float) PHPExcel_Calculation_Functions::flattenSingleValue($base);
  467. if ((!is_numeric($base)) || (!is_numeric($number))) {
  468. return PHPExcel_Calculation_Functions::VALUE();
  469. }
  470. if (($base <= 0) || ($number <= 0)) {
  471. return PHPExcel_Calculation_Functions::NaN();
  472. }
  473. return log($number, $base);
  474. }
  475. /**
  476. * MDETERM
  477. *
  478. * Returns the matrix determinant of an array.
  479. *
  480. * Excel Function:
  481. * MDETERM(array)
  482. *
  483. * @access public
  484. * @category Mathematical and Trigonometric Functions
  485. * @param array $matrixValues A matrix of values
  486. * @return float
  487. */
  488. public static function MDETERM($matrixValues)
  489. {
  490. $matrixData = array();
  491. if (!is_array($matrixValues)) {
  492. $matrixValues = array(array($matrixValues));
  493. }
  494. $row = $maxColumn = 0;
  495. foreach ($matrixValues as $matrixRow) {
  496. if (!is_array($matrixRow)) {
  497. $matrixRow = array($matrixRow);
  498. }
  499. $column = 0;
  500. foreach ($matrixRow as $matrixCell) {
  501. if ((is_string($matrixCell)) || ($matrixCell === null)) {
  502. return PHPExcel_Calculation_Functions::VALUE();
  503. }
  504. $matrixData[$column][$row] = $matrixCell;
  505. ++$column;
  506. }
  507. if ($column > $maxColumn) {
  508. $maxColumn = $column;
  509. }
  510. ++$row;
  511. }
  512. if ($row != $maxColumn) {
  513. return PHPExcel_Calculation_Functions::VALUE();
  514. }
  515. try {
  516. $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData);
  517. return $matrix->det();
  518. } catch (PHPExcel_Exception $ex) {
  519. return PHPExcel_Calculation_Functions::VALUE();
  520. }
  521. }
  522. /**
  523. * MINVERSE
  524. *
  525. * Returns the inverse matrix for the matrix stored in an array.
  526. *
  527. * Excel Function:
  528. * MINVERSE(array)
  529. *
  530. * @access public
  531. * @category Mathematical and Trigonometric Functions
  532. * @param array $matrixValues A matrix of values
  533. * @return array
  534. */
  535. public static function MINVERSE($matrixValues)
  536. {
  537. $matrixData = array();
  538. if (!is_array($matrixValues)) {
  539. $matrixValues = array(array($matrixValues));
  540. }
  541. $row = $maxColumn = 0;
  542. foreach ($matrixValues as $matrixRow) {
  543. if (!is_array($matrixRow)) {
  544. $matrixRow = array($matrixRow);
  545. }
  546. $column = 0;
  547. foreach ($matrixRow as $matrixCell) {
  548. if ((is_string($matrixCell)) || ($matrixCell === null)) {
  549. return PHPExcel_Calculation_Functions::VALUE();
  550. }
  551. $matrixData[$column][$row] = $matrixCell;
  552. ++$column;
  553. }
  554. if ($column > $maxColumn) {
  555. $maxColumn = $column;
  556. }
  557. ++$row;
  558. }
  559. if ($row != $maxColumn) {
  560. return PHPExcel_Calculation_Functions::VALUE();
  561. }
  562. try {
  563. $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData);
  564. return $matrix->inverse()->getArray();
  565. } catch (PHPExcel_Exception $ex) {
  566. return PHPExcel_Calculation_Functions::VALUE();
  567. }
  568. }
  569. /**
  570. * MMULT
  571. *
  572. * @param array $matrixData1 A matrix of values
  573. * @param array $matrixData2 A matrix of values
  574. * @return array
  575. */
  576. public static function MMULT($matrixData1, $matrixData2)
  577. {
  578. $matrixAData = $matrixBData = array();
  579. if (!is_array($matrixData1)) {
  580. $matrixData1 = array(array($matrixData1));
  581. }
  582. if (!is_array($matrixData2)) {
  583. $matrixData2 = array(array($matrixData2));
  584. }
  585. try {
  586. $rowA = 0;
  587. foreach ($matrixData1 as $matrixRow) {
  588. if (!is_array($matrixRow)) {
  589. $matrixRow = array($matrixRow);
  590. }
  591. $columnA = 0;
  592. foreach ($matrixRow as $matrixCell) {
  593. if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
  594. return PHPExcel_Calculation_Functions::VALUE();
  595. }
  596. $matrixAData[$rowA][$columnA] = $matrixCell;
  597. ++$columnA;
  598. }
  599. ++$rowA;
  600. }
  601. $matrixA = new PHPExcel_Shared_JAMA_Matrix($matrixAData);
  602. $rowB = 0;
  603. foreach ($matrixData2 as $matrixRow) {
  604. if (!is_array($matrixRow)) {
  605. $matrixRow = array($matrixRow);
  606. }
  607. $columnB = 0;
  608. foreach ($matrixRow as $matrixCell) {
  609. if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
  610. return PHPExcel_Calculation_Functions::VALUE();
  611. }
  612. $matrixBData[$rowB][$columnB] = $matrixCell;
  613. ++$columnB;
  614. }
  615. ++$rowB;
  616. }
  617. $matrixB = new PHPExcel_Shared_JAMA_Matrix($matrixBData);
  618. if ($columnA != $rowB) {
  619. return PHPExcel_Calculation_Functions::VALUE();
  620. }
  621. return $matrixA->times($matrixB)->getArray();
  622. } catch (PHPExcel_Exception $ex) {
  623. var_dump($ex->getMessage());
  624. return PHPExcel_Calculation_Functions::VALUE();
  625. }
  626. }
  627. /**
  628. * MOD
  629. *
  630. * @param int $a Dividend
  631. * @param int $b Divisor
  632. * @return int Remainder
  633. */
  634. public static function MOD($a = 1, $b = 1)
  635. {
  636. $a = PHPExcel_Calculation_Functions::flattenSingleValue($a);
  637. $b = PHPExcel_Calculation_Functions::flattenSingleValue($b);
  638. if ($b == 0.0) {
  639. return PHPExcel_Calculation_Functions::DIV0();
  640. } elseif (($a < 0.0) && ($b > 0.0)) {
  641. return $b - fmod(abs($a), $b);
  642. } elseif (($a > 0.0) && ($b < 0.0)) {
  643. return $b + fmod($a, abs($b));
  644. }
  645. return fmod($a, $b);
  646. }
  647. /**
  648. * MROUND
  649. *
  650. * Rounds a number to the nearest multiple of a specified value
  651. *
  652. * @param float $number Number to round
  653. * @param int $multiple Multiple to which you want to round $number
  654. * @return float Rounded Number
  655. */
  656. public static function MROUND($number, $multiple)
  657. {
  658. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  659. $multiple = PHPExcel_Calculation_Functions::flattenSingleValue($multiple);
  660. if ((is_numeric($number)) && (is_numeric($multiple))) {
  661. if ($multiple == 0) {
  662. return 0;
  663. }
  664. if ((self::SIGN($number)) == (self::SIGN($multiple))) {
  665. $multiplier = 1 / $multiple;
  666. return round($number * $multiplier) / $multiplier;
  667. }
  668. return PHPExcel_Calculation_Functions::NaN();
  669. }
  670. return PHPExcel_Calculation_Functions::VALUE();
  671. }
  672. /**
  673. * MULTINOMIAL
  674. *
  675. * Returns the ratio of the factorial of a sum of values to the product of factorials.
  676. *
  677. * @param array of mixed Data Series
  678. * @return float
  679. */
  680. public static function MULTINOMIAL()
  681. {
  682. $summer = 0;
  683. $divisor = 1;
  684. // Loop through arguments
  685. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
  686. // Is it a numeric value?
  687. if (is_numeric($arg)) {
  688. if ($arg < 1) {
  689. return PHPExcel_Calculation_Functions::NaN();
  690. }
  691. $summer += floor($arg);
  692. $divisor *= self::FACT($arg);
  693. } else {
  694. return PHPExcel_Calculation_Functions::VALUE();
  695. }
  696. }
  697. // Return
  698. if ($summer > 0) {
  699. $summer = self::FACT($summer);
  700. return $summer / $divisor;
  701. }
  702. return 0;
  703. }
  704. /**
  705. * ODD
  706. *
  707. * Returns number rounded up to the nearest odd integer.
  708. *
  709. * @param float $number Number to round
  710. * @return int Rounded Number
  711. */
  712. public static function ODD($number)
  713. {
  714. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  715. if (is_null($number)) {
  716. return 1;
  717. } elseif (is_bool($number)) {
  718. return 1;
  719. } elseif (is_numeric($number)) {
  720. $significance = self::SIGN($number);
  721. if ($significance == 0) {
  722. return 1;
  723. }
  724. $result = self::CEILING($number, $significance);
  725. if ($result == self::EVEN($result)) {
  726. $result += $significance;
  727. }
  728. return (int) $result;
  729. }
  730. return PHPExcel_Calculation_Functions::VALUE();
  731. }
  732. /**
  733. * POWER
  734. *
  735. * Computes x raised to the power y.
  736. *
  737. * @param float $x
  738. * @param float $y
  739. * @return float
  740. */
  741. public static function POWER($x = 0, $y = 2)
  742. {
  743. $x = PHPExcel_Calculation_Functions::flattenSingleValue($x);
  744. $y = PHPExcel_Calculation_Functions::flattenSingleValue($y);
  745. // Validate parameters
  746. if ($x == 0.0 && $y == 0.0) {
  747. return PHPExcel_Calculation_Functions::NaN();
  748. } elseif ($x == 0.0 && $y < 0.0) {
  749. return PHPExcel_Calculation_Functions::DIV0();
  750. }
  751. // Return
  752. $result = pow($x, $y);
  753. return (!is_nan($result) && !is_infinite($result)) ? $result : PHPExcel_Calculation_Functions::NaN();
  754. }
  755. /**
  756. * PRODUCT
  757. *
  758. * PRODUCT returns the product of all the values and cells referenced in the argument list.
  759. *
  760. * Excel Function:
  761. * PRODUCT(value1[,value2[, ...]])
  762. *
  763. * @access public
  764. * @category Mathematical and Trigonometric Functions
  765. * @param mixed $arg,... Data values
  766. * @return float
  767. */
  768. public static function PRODUCT()
  769. {
  770. // Return value
  771. $returnValue = null;
  772. // Loop through arguments
  773. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
  774. // Is it a numeric value?
  775. if ((is_numeric($arg)) && (!is_string($arg))) {
  776. if (is_null($returnValue)) {
  777. $returnValue = $arg;
  778. } else {
  779. $returnValue *= $arg;
  780. }
  781. }
  782. }
  783. // Return
  784. if (is_null($returnValue)) {
  785. return 0;
  786. }
  787. return $returnValue;
  788. }
  789. /**
  790. * QUOTIENT
  791. *
  792. * QUOTIENT function returns the integer portion of a division. Numerator is the divided number
  793. * and denominator is the divisor.
  794. *
  795. * Excel Function:
  796. * QUOTIENT(value1[,value2[, ...]])
  797. *
  798. * @access public
  799. * @category Mathematical and Trigonometric Functions
  800. * @param mixed $arg,... Data values
  801. * @return float
  802. */
  803. public static function QUOTIENT()
  804. {
  805. // Return value
  806. $returnValue = null;
  807. // Loop through arguments
  808. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
  809. // Is it a numeric value?
  810. if ((is_numeric($arg)) && (!is_string($arg))) {
  811. if (is_null($returnValue)) {
  812. $returnValue = ($arg == 0) ? 0 : $arg;
  813. } else {
  814. if (($returnValue == 0) || ($arg == 0)) {
  815. $returnValue = 0;
  816. } else {
  817. $returnValue /= $arg;
  818. }
  819. }
  820. }
  821. }
  822. // Return
  823. return intval($returnValue);
  824. }
  825. /**
  826. * RAND
  827. *
  828. * @param int $min Minimal value
  829. * @param int $max Maximal value
  830. * @return int Random number
  831. */
  832. public static function RAND($min = 0, $max = 0)
  833. {
  834. $min = PHPExcel_Calculation_Functions::flattenSingleValue($min);
  835. $max = PHPExcel_Calculation_Functions::flattenSingleValue($max);
  836. if ($min == 0 && $max == 0) {
  837. return (mt_rand(0, 10000000)) / 10000000;
  838. } else {
  839. return mt_rand($min, $max);
  840. }
  841. }
  842. public static function ROMAN($aValue, $style = 0)
  843. {
  844. $aValue = PHPExcel_Calculation_Functions::flattenSingleValue($aValue);
  845. $style = (is_null($style)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($style);
  846. if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) {
  847. return PHPExcel_Calculation_Functions::VALUE();
  848. }
  849. $aValue = (integer) $aValue;
  850. if ($aValue == 0) {
  851. return '';
  852. }
  853. $mill = array('', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM');
  854. $cent = array('', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM');
  855. $tens = array('', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC');
  856. $ones = array('', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX');
  857. $roman = '';
  858. while ($aValue > 5999) {
  859. $roman .= 'M';
  860. $aValue -= 1000;
  861. }
  862. $m = self::romanCut($aValue, 1000);
  863. $aValue %= 1000;
  864. $c = self::romanCut($aValue, 100);
  865. $aValue %= 100;
  866. $t = self::romanCut($aValue, 10);
  867. $aValue %= 10;
  868. return $roman.$mill[$m].$cent[$c].$tens[$t].$ones[$aValue];
  869. }
  870. /**
  871. * ROUNDUP
  872. *
  873. * Rounds a number up to a specified number of decimal places
  874. *
  875. * @param float $number Number to round
  876. * @param int $digits Number of digits to which you want to round $number
  877. * @return float Rounded Number
  878. */
  879. public static function ROUNDUP($number, $digits)
  880. {
  881. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  882. $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits);
  883. if ((is_numeric($number)) && (is_numeric($digits))) {
  884. $significance = pow(10, (int) $digits);
  885. if ($number < 0.0) {
  886. return floor($number * $significance) / $significance;
  887. } else {
  888. return ceil($number * $significance) / $significance;
  889. }
  890. }
  891. return PHPExcel_Calculation_Functions::VALUE();
  892. }
  893. /**
  894. * ROUNDDOWN
  895. *
  896. * Rounds a number down to a specified number of decimal places
  897. *
  898. * @param float $number Number to round
  899. * @param int $digits Number of digits to which you want to round $number
  900. * @return float Rounded Number
  901. */
  902. public static function ROUNDDOWN($number, $digits)
  903. {
  904. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  905. $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits);
  906. if ((is_numeric($number)) && (is_numeric($digits))) {
  907. $significance = pow(10, (int) $digits);
  908. if ($number < 0.0) {
  909. return ceil($number * $significance) / $significance;
  910. } else {
  911. return floor($number * $significance) / $significance;
  912. }
  913. }
  914. return PHPExcel_Calculation_Functions::VALUE();
  915. }
  916. /**
  917. * SERIESSUM
  918. *
  919. * Returns the sum of a power series
  920. *
  921. * @param float $x Input value to the power series
  922. * @param float $n Initial power to which you want to raise $x
  923. * @param float $m Step by which to increase $n for each term in the series
  924. * @param array of mixed Data Series
  925. * @return float
  926. */
  927. public static function SERIESSUM()
  928. {
  929. $returnValue = 0;
  930. // Loop through arguments
  931. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  932. $x = array_shift($aArgs);
  933. $n = array_shift($aArgs);
  934. $m = array_shift($aArgs);
  935. if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) {
  936. // Calculate
  937. $i = 0;
  938. foreach ($aArgs as $arg) {
  939. // Is it a numeric value?
  940. if ((is_numeric($arg)) && (!is_string($arg))) {
  941. $returnValue += $arg * pow($x, $n + ($m * $i++));
  942. } else {
  943. return PHPExcel_Calculation_Functions::VALUE();
  944. }
  945. }
  946. return $returnValue;
  947. }
  948. return PHPExcel_Calculation_Functions::VALUE();
  949. }
  950. /**
  951. * SIGN
  952. *
  953. * Determines the sign of a number. Returns 1 if the number is positive, zero (0)
  954. * if the number is 0, and -1 if the number is negative.
  955. *
  956. * @param float $number Number to round
  957. * @return int sign value
  958. */
  959. public static function SIGN($number)
  960. {
  961. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  962. if (is_bool($number)) {
  963. return (int) $number;
  964. }
  965. if (is_numeric($number)) {
  966. if ($number == 0.0) {
  967. return 0;
  968. }
  969. return $number / abs($number);
  970. }
  971. return PHPExcel_Calculation_Functions::VALUE();
  972. }
  973. /**
  974. * SQRTPI
  975. *
  976. * Returns the square root of (number * pi).
  977. *
  978. * @param float $number Number
  979. * @return float Square Root of Number * Pi
  980. */
  981. public static function SQRTPI($number)
  982. {
  983. $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
  984. if (is_numeric($number)) {
  985. if ($number < 0) {
  986. return PHPExcel_Calculation_Functions::NaN();
  987. }
  988. return sqrt($number * M_PI) ;
  989. }
  990. return PHPExcel_Calculation_Functions::VALUE();
  991. }
  992. /**
  993. * SUBTOTAL
  994. *
  995. * Returns a subtotal in a list or database.
  996. *
  997. * @param int the number 1 to 11 that specifies which function to
  998. * use in calculating subtotals within a list.
  999. * @param array of mixed Data Series
  1000. * @return float
  1001. */
  1002. public static function SUBTOTAL()
  1003. {
  1004. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1005. // Calculate
  1006. $subtotal = array_shift($aArgs);
  1007. if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
  1008. switch ($subtotal) {
  1009. case 1:
  1010. return PHPExcel_Calculation_Statistical::AVERAGE($aArgs);
  1011. case 2:
  1012. return PHPExcel_Calculation_Statistical::COUNT($aArgs);
  1013. case 3:
  1014. return PHPExcel_Calculation_Statistical::COUNTA($aArgs);
  1015. case 4:
  1016. return PHPExcel_Calculation_Statistical::MAX($aArgs);
  1017. case 5:
  1018. return PHPExcel_Calculation_Statistical::MIN($aArgs);
  1019. case 6:
  1020. return self::PRODUCT($aArgs);
  1021. case 7:
  1022. return PHPExcel_Calculation_Statistical::STDEV($aArgs);
  1023. case 8:
  1024. return PHPExcel_Calculation_Statistical::STDEVP($aArgs);
  1025. case 9:
  1026. return self::SUM($aArgs);
  1027. case 10:
  1028. return PHPExcel_Calculation_Statistical::VARFunc($aArgs);
  1029. case 11:
  1030. return PHPExcel_Calculation_Statistical::VARP($aArgs);
  1031. }
  1032. }
  1033. return PHPExcel_Calculation_Functions::VALUE();
  1034. }
  1035. /**
  1036. * SUM
  1037. *
  1038. * SUM computes the sum of all the values and cells referenced in the argument list.
  1039. *
  1040. * Excel Function:
  1041. * SUM(value1[,value2[, ...]])
  1042. *
  1043. * @access public
  1044. * @category Mathematical and Trigonometric Functions
  1045. * @param mixed $arg,... Data values
  1046. * @return float
  1047. */
  1048. public static function SUM()
  1049. {
  1050. $returnValue = 0;
  1051. // Loop through the arguments
  1052. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
  1053. // Is it a numeric value?
  1054. if ((is_numeric($arg)) && (!is_string($arg))) {
  1055. $returnValue += $arg;
  1056. }
  1057. }
  1058. return $returnValue;
  1059. }
  1060. /**
  1061. * SUMIF
  1062. *
  1063. * Counts the number of cells that contain numbers within the list of arguments
  1064. *
  1065. * Excel Function:
  1066. * SUMIF(value1[,value2[, ...]],condition)
  1067. *
  1068. * @access public
  1069. * @category Mathematical and Trigonometric Functions
  1070. * @param mixed $arg,... Data values
  1071. * @param string $condition The criteria that defines which cells will be summed.
  1072. * @return float
  1073. */
  1074. public static function SUMIF($aArgs, $condition, $sumArgs = array())
  1075. {
  1076. $returnValue = 0;
  1077. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  1078. $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
  1079. if (empty($sumArgs)) {
  1080. $sumArgs = $aArgs;
  1081. }
  1082. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  1083. // Loop through arguments
  1084. foreach ($aArgs as $key => $arg) {
  1085. if (!is_numeric($arg)) {
  1086. $arg = str_replace('"', '""', $arg);
  1087. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  1088. }
  1089. $testCondition = '='.$arg.$condition;
  1090. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  1091. // Is it a value within our criteria
  1092. $returnValue += $sumArgs[$key];
  1093. }
  1094. }
  1095. return $returnValue;
  1096. }
  1097. /**
  1098. * SUMIFS
  1099. *
  1100. * Counts the number of cells that contain numbers within the list of arguments
  1101. *
  1102. * Excel Function:
  1103. * SUMIFS(value1[,value2[, ...]],condition)
  1104. *
  1105. * @access public
  1106. * @category Mathematical and Trigonometric Functions
  1107. * @param mixed $arg,... Data values
  1108. * @param string $condition The criteria that defines which cells will be summed.
  1109. * @return float
  1110. */
  1111. public static function SUMIFS() {
  1112. $arrayList = func_get_args();
  1113. $sumArgs = PHPExcel_Calculation_Functions::flattenArray(array_shift($arrayList));
  1114. while (count($arrayList) > 0) {
  1115. $aArgsArray[] = PHPExcel_Calculation_Functions::flattenArray(array_shift($arrayList));
  1116. $conditions[] = PHPExcel_Calculation_Functions::ifCondition(array_shift($arrayList));
  1117. }
  1118. // Loop through each set of arguments and conditions
  1119. foreach ($conditions as $index => $condition) {
  1120. $aArgs = $aArgsArray[$index];
  1121. $wildcard = false;
  1122. if ((strpos($condition, '*') !== false) || (strpos($condition, '?') !== false)) {
  1123. // * and ? are wildcard characters.
  1124. // Use ~* and ~? for literal star and question mark
  1125. // Code logic doesn't yet handle escaping
  1126. $condition = trim(ltrim($condition, '=<>'), '"');
  1127. $wildcard = true;
  1128. }
  1129. // Loop through arguments
  1130. foreach ($aArgs as $key => $arg) {
  1131. if ($wildcard) {
  1132. if (!fnmatch($condition, $arg, FNM_CASEFOLD)) {
  1133. // Is it a value within our criteria
  1134. $sumArgs[$key] = 0.0;
  1135. }
  1136. } else {
  1137. if (!is_numeric($arg)) {
  1138. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  1139. }
  1140. $testCondition = '='.$arg.$condition;
  1141. if (!PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  1142. // Is it a value within our criteria
  1143. $sumArgs[$key] = 0.0;
  1144. }
  1145. }
  1146. }
  1147. }
  1148. // Return
  1149. return array_sum($sumArgs);
  1150. }
  1151. /**
  1152. * SUMPRODUCT
  1153. *
  1154. * Excel Function:
  1155. * SUMPRODUCT(value1[,value2[, ...]])
  1156. *
  1157. * @access public
  1158. * @category Mathematical and Trigonometric Functions
  1159. * @param mixed $arg,... Data values
  1160. * @return float
  1161. */
  1162. public static function SUMPRODUCT()
  1163. {
  1164. $arrayList = func_get_args();
  1165. $wrkArray = PHPExcel_Calculation_Functions::flattenArray(array_shift($arrayList));
  1166. $wrkCellCount = count($wrkArray);
  1167. for ($i=0; $i< $wrkCellCount; ++$i) {
  1168. if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) {
  1169. $wrkArray[$i] = 0;
  1170. }
  1171. }
  1172. foreach ($arrayList as $matrixData) {
  1173. $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData);
  1174. $count = count($array2);
  1175. if ($wrkCellCount != $count) {
  1176. return PHPExcel_Calculation_Functions::VALUE();
  1177. }
  1178. foreach ($array2 as $i => $val) {
  1179. if ((!is_numeric($val)) || (is_string($val))) {
  1180. $val = 0;
  1181. }
  1182. $wrkArray[$i] *= $val;
  1183. }
  1184. }
  1185. return array_sum($wrkArray);
  1186. }
  1187. /**
  1188. * SUMSQ
  1189. *
  1190. * SUMSQ returns the sum of the squares of the arguments
  1191. *
  1192. * Excel Function:
  1193. * SUMSQ(value1[,value2[, ...]])
  1194. *
  1195. * @access public
  1196. * @category Mathematical and Trigonometric Functions
  1197. * @param mixed $arg,... Data values
  1198. * @return float
  1199. */
  1200. public static function SUMSQ()
  1201. {
  1202. $returnValue = 0;
  1203. // Loop through arguments
  1204. foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
  1205. // Is it a numeric value?
  1206. if ((is_numeric($arg)) && (!is_string($arg))) {
  1207. $returnValue += ($arg * $arg);
  1208. }
  1209. }
  1210. return $returnValue;
  1211. }
  1212. /**
  1213. * SUMX2MY2
  1214. *
  1215. * @param mixed[] $matrixData1 Matrix #1
  1216. * @param mixed[] $matrixData2 Matrix #2
  1217. * @return float
  1218. */
  1219. public static function SUMX2MY2($matrixData1, $matrixData2)
  1220. {
  1221. $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1);
  1222. $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2);
  1223. $count = min(count($array1), count($array2));
  1224. $result = 0;
  1225. for ($i = 0; $i < $count; ++$i) {
  1226. if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
  1227. ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
  1228. $result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]);
  1229. }
  1230. }
  1231. return $result;
  1232. }
  1233. /**
  1234. * SUMX2PY2
  1235. *
  1236. * @param mixed[] $matrixData1 Matrix #1
  1237. * @param mixed[] $matrixData2 Matrix #2
  1238. * @return float
  1239. */
  1240. public static function SUMX2PY2($matrixData1, $matrixData2)
  1241. {
  1242. $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1);
  1243. $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2);
  1244. $count = min(count($array1), count($array2));
  1245. $result = 0;
  1246. for ($i = 0; $i < $count; ++$i) {
  1247. if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
  1248. ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
  1249. $result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]);
  1250. }
  1251. }
  1252. return $result;
  1253. }
  1254. /**
  1255. * SUMXMY2
  1256. *
  1257. * @param mixed[] $matrixData1 Matrix #1
  1258. * @param mixed[] $matrixData2 Matrix #2
  1259. * @return float
  1260. */
  1261. public static function SUMXMY2($matrixData1, $matrixData2)
  1262. {
  1263. $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1);
  1264. $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2);
  1265. $count = min(count($array1), count($array2));
  1266. $result = 0;
  1267. for ($i = 0; $i < $count; ++$i) {
  1268. if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
  1269. ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
  1270. $result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]);
  1271. }
  1272. }
  1273. return $result;
  1274. }
  1275. /**
  1276. * TRUNC
  1277. *
  1278. * Truncates value to the number of fractional digits by number_digits.
  1279. *
  1280. * @param float $value
  1281. * @param int $digits
  1282. * @return float Truncated value
  1283. */
  1284. public static function TRUNC($value = 0, $digits = 0)
  1285. {
  1286. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1287. $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits);
  1288. // Validate parameters
  1289. if ((!is_numeric($value)) || (!is_numeric($digits))) {
  1290. return PHPExcel_Calculation_Functions::VALUE();
  1291. }
  1292. $digits = floor($digits);
  1293. // Truncate
  1294. $adjust = pow(10, $digits);
  1295. if (($digits > 0) && (rtrim(intval((abs($value) - abs(intval($value))) * $adjust), '0') < $adjust/10)) {
  1296. return $value;
  1297. }
  1298. return (intval($value * $adjust)) / $adjust;
  1299. }
  1300. }