PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/common/libraries/plugin/phpexcel/PHPExcel/Calculation/Financial.php

https://bitbucket.org/renaatdemuynck/chamilo
PHP | 2064 lines | 1284 code | 231 blank | 549 comment | 316 complexity | 29cfe0668c547fcf32a0ebce829d0a60 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2011 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 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version 1.7.6, 2011-02-27
  26. */
  27. /** PHPExcel root directory */
  28. if (! defined('PHPEXCEL_ROOT'))
  29. {
  30. /**
  31. * @ignore
  32. */
  33. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  34. require (PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  35. }
  36. /** FINANCIAL_MAX_ITERATIONS */
  37. define('FINANCIAL_MAX_ITERATIONS', 128);
  38. /** FINANCIAL_PRECISION */
  39. define('FINANCIAL_PRECISION', 1.0e-08);
  40. /**
  41. * PHPExcel_Calculation_Financial
  42. *
  43. * @category PHPExcel
  44. * @package PHPExcel_Calculation
  45. * @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  46. */
  47. class PHPExcel_Calculation_Financial
  48. {
  49. private static function _lastDayOfMonth($testDate)
  50. {
  51. $date = clone $testDate;
  52. $date->modify('+1 day');
  53. return ($date->format('d') == 1);
  54. } // function _lastDayOfMonth()
  55. private static function _firstDayOfMonth($testDate)
  56. {
  57. $date = clone $testDate;
  58. return ($date->format('d') == 1);
  59. } // function _lastDayOfMonth()
  60. private static function _coupFirstPeriodDate($settlement, $maturity, $frequency, $next)
  61. {
  62. $months = 12 / $frequency;
  63. $result = PHPExcel_Shared_Date :: ExcelToPHPObject($maturity);
  64. $eom = self :: _lastDayOfMonth($result);
  65. while ($settlement < PHPExcel_Shared_Date :: PHPToExcel($result))
  66. {
  67. $result->modify('-' . $months . ' months');
  68. }
  69. if ($next)
  70. {
  71. $result->modify('+' . $months . ' months');
  72. }
  73. if ($eom)
  74. {
  75. $result->modify('-1 day');
  76. }
  77. return PHPExcel_Shared_Date :: PHPToExcel($result);
  78. } // function _coupFirstPeriodDate()
  79. private static function _validFrequency($frequency)
  80. {
  81. if (($frequency == 1) || ($frequency == 2) || ($frequency == 4))
  82. {
  83. return true;
  84. }
  85. if ((PHPExcel_Calculation_Functions :: getCompatibilityMode() == PHPExcel_Calculation_Functions :: COMPATIBILITY_GNUMERIC) && (($frequency == 6) || ($frequency == 12)))
  86. {
  87. return true;
  88. }
  89. return false;
  90. } // function _validFrequency()
  91. private static function _daysPerYear($year, $basis)
  92. {
  93. switch ($basis)
  94. {
  95. case 0 :
  96. case 2 :
  97. case 4 :
  98. $daysPerYear = 360;
  99. break;
  100. case 3 :
  101. $daysPerYear = 365;
  102. break;
  103. case 1 :
  104. if (PHPExcel_Calculation_DateTime :: _isLeapYear($year))
  105. {
  106. $daysPerYear = 366;
  107. }
  108. else
  109. {
  110. $daysPerYear = 365;
  111. }
  112. break;
  113. default :
  114. return PHPExcel_Calculation_Functions :: NaN();
  115. }
  116. return $daysPerYear;
  117. } // function _daysPerYear()
  118. private static function _interestAndPrincipal($rate = 0, $per = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
  119. {
  120. $pmt = self :: PMT($rate, $nper, $pv, $fv, $type);
  121. $capital = $pv;
  122. for($i = 1; $i <= $per; ++ $i)
  123. {
  124. $interest = ($type && $i == 1) ? 0 : - $capital * $rate;
  125. $principal = $pmt - $interest;
  126. $capital += $principal;
  127. }
  128. return array($interest, $principal);
  129. } // function _interestAndPrincipal()
  130. /**
  131. * ACCRINT
  132. *
  133. * Returns the discount rate for a security.
  134. *
  135. * @param mixed issue The security's issue date.
  136. * @param mixed firstinter The security's first interest date.
  137. * @param mixed settlement The security's settlement date.
  138. * @param float rate The security's annual coupon rate.
  139. * @param float par The security's par value.
  140. * @param int basis The type of day count to use.
  141. * 0 or omitted US (NASD) 30/360
  142. * 1 Actual/actual
  143. * 2 Actual/360
  144. * 3 Actual/365
  145. * 4 European 30/360
  146. * @return float
  147. */
  148. public static function ACCRINT($issue, $firstinter, $settlement, $rate, $par = 1000, $frequency = 1, $basis = 0)
  149. {
  150. $issue = PHPExcel_Calculation_Functions :: flattenSingleValue($issue);
  151. $firstinter = PHPExcel_Calculation_Functions :: flattenSingleValue($firstinter);
  152. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  153. $rate = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  154. $par = (is_null($par)) ? 1000 : (float) PHPExcel_Calculation_Functions :: flattenSingleValue($par);
  155. $frequency = (is_null($frequency)) ? 1 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  156. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  157. // Validate
  158. if ((is_numeric($rate)) && (is_numeric($par)))
  159. {
  160. if (($rate <= 0) || ($par <= 0))
  161. {
  162. return PHPExcel_Calculation_Functions :: NaN();
  163. }
  164. $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime :: YEARFRAC($issue, $settlement, $basis);
  165. if (! is_numeric($daysBetweenIssueAndSettlement))
  166. {
  167. // return date error
  168. return $daysBetweenIssueAndSettlement;
  169. }
  170. return $par * $rate * $daysBetweenIssueAndSettlement;
  171. }
  172. return PHPExcel_Calculation_Functions :: VALUE();
  173. } // function ACCRINT()
  174. /**
  175. * ACCRINTM
  176. *
  177. * Returns the discount rate for a security.
  178. *
  179. * @param mixed issue The security's issue date.
  180. * @param mixed settlement The security's settlement date.
  181. * @param float rate The security's annual coupon rate.
  182. * @param float par The security's par value.
  183. * @param int basis The type of day count to use.
  184. * 0 or omitted US (NASD) 30/360
  185. * 1 Actual/actual
  186. * 2 Actual/360
  187. * 3 Actual/365
  188. * 4 European 30/360
  189. * @return float
  190. */
  191. public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis = 0)
  192. {
  193. $issue = PHPExcel_Calculation_Functions :: flattenSingleValue($issue);
  194. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  195. $rate = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  196. $par = (is_null($par)) ? 1000 : (float) PHPExcel_Calculation_Functions :: flattenSingleValue($par);
  197. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  198. // Validate
  199. if ((is_numeric($rate)) && (is_numeric($par)))
  200. {
  201. if (($rate <= 0) || ($par <= 0))
  202. {
  203. return PHPExcel_Calculation_Functions :: NaN();
  204. }
  205. $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime :: YEARFRAC($issue, $settlement, $basis);
  206. if (! is_numeric($daysBetweenIssueAndSettlement))
  207. {
  208. // return date error
  209. return $daysBetweenIssueAndSettlement;
  210. }
  211. return $par * $rate * $daysBetweenIssueAndSettlement;
  212. }
  213. return PHPExcel_Calculation_Functions :: VALUE();
  214. } // function ACCRINTM()
  215. public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0)
  216. {
  217. $cost = PHPExcel_Calculation_Functions :: flattenSingleValue($cost);
  218. $purchased = PHPExcel_Calculation_Functions :: flattenSingleValue($purchased);
  219. $firstPeriod = PHPExcel_Calculation_Functions :: flattenSingleValue($firstPeriod);
  220. $salvage = PHPExcel_Calculation_Functions :: flattenSingleValue($salvage);
  221. $period = floor(PHPExcel_Calculation_Functions :: flattenSingleValue($period));
  222. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  223. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  224. $fUsePer = 1.0 / $rate;
  225. if ($fUsePer < 3.0)
  226. {
  227. $amortiseCoeff = 1.0;
  228. }
  229. elseif ($fUsePer < 5.0)
  230. {
  231. $amortiseCoeff = 1.5;
  232. }
  233. elseif ($fUsePer <= 6.0)
  234. {
  235. $amortiseCoeff = 2.0;
  236. }
  237. else
  238. {
  239. $amortiseCoeff = 2.5;
  240. }
  241. $rate *= $amortiseCoeff;
  242. $fNRate = round(PHPExcel_Calculation_DateTime :: YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost, 0);
  243. $cost -= $fNRate;
  244. $fRest = $cost - $salvage;
  245. for($n = 0; $n < $period; ++ $n)
  246. {
  247. $fNRate = round($rate * $cost, 0);
  248. $fRest -= $fNRate;
  249. if ($fRest < 0.0)
  250. {
  251. switch ($period - $n)
  252. {
  253. case 0 :
  254. case 1 :
  255. return round($cost * 0.5, 0);
  256. break;
  257. default :
  258. return 0.0;
  259. break;
  260. }
  261. }
  262. $cost -= $fNRate;
  263. }
  264. return $fNRate;
  265. } // function AMORDEGRC()
  266. public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0)
  267. {
  268. $cost = PHPExcel_Calculation_Functions :: flattenSingleValue($cost);
  269. $purchased = PHPExcel_Calculation_Functions :: flattenSingleValue($purchased);
  270. $firstPeriod = PHPExcel_Calculation_Functions :: flattenSingleValue($firstPeriod);
  271. $salvage = PHPExcel_Calculation_Functions :: flattenSingleValue($salvage);
  272. $period = PHPExcel_Calculation_Functions :: flattenSingleValue($period);
  273. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  274. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  275. $fOneRate = $cost * $rate;
  276. $fCostDelta = $cost - $salvage;
  277. // Note, quirky variation for leap years on the YEARFRAC for this function
  278. $purchasedYear = PHPExcel_Calculation_DateTime :: YEAR($purchased);
  279. $yearFrac = PHPExcel_Calculation_DateTime :: YEARFRAC($purchased, $firstPeriod, $basis);
  280. if (($basis == 1) && ($yearFrac < 1) && (PHPExcel_Calculation_DateTime :: _isLeapYear($purchasedYear)))
  281. {
  282. $yearFrac *= 365 / 366;
  283. }
  284. $f0Rate = $yearFrac * $rate * $cost;
  285. $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate);
  286. if ($period == 0)
  287. {
  288. return $f0Rate;
  289. }
  290. elseif ($period <= $nNumOfFullPeriods)
  291. {
  292. return $fOneRate;
  293. }
  294. elseif ($period == ($nNumOfFullPeriods + 1))
  295. {
  296. return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate);
  297. }
  298. else
  299. {
  300. return 0.0;
  301. }
  302. } // function AMORLINC()
  303. public static function COUPDAYBS($settlement, $maturity, $frequency, $basis = 0)
  304. {
  305. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  306. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  307. $frequency = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  308. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  309. if (is_string($settlement = PHPExcel_Calculation_DateTime :: _getDateValue($settlement)))
  310. {
  311. return PHPExcel_Calculation_Functions :: VALUE();
  312. }
  313. if (is_string($maturity = PHPExcel_Calculation_DateTime :: _getDateValue($maturity)))
  314. {
  315. return PHPExcel_Calculation_Functions :: VALUE();
  316. }
  317. if (($settlement > $maturity) || (! self :: _validFrequency($frequency)) || (($basis < 0) || ($basis > 4)))
  318. {
  319. return PHPExcel_Calculation_Functions :: NaN();
  320. }
  321. $daysPerYear = self :: _daysPerYear(PHPExcel_Calculation_DateTime :: YEAR($settlement), $basis);
  322. $prev = self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, False);
  323. return PHPExcel_Calculation_DateTime :: YEARFRAC($prev, $settlement, $basis) * $daysPerYear;
  324. } // function COUPDAYBS()
  325. public static function COUPDAYS($settlement, $maturity, $frequency, $basis = 0)
  326. {
  327. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  328. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  329. $frequency = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  330. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  331. if (is_string($settlement = PHPExcel_Calculation_DateTime :: _getDateValue($settlement)))
  332. {
  333. return PHPExcel_Calculation_Functions :: VALUE();
  334. }
  335. if (is_string($maturity = PHPExcel_Calculation_DateTime :: _getDateValue($maturity)))
  336. {
  337. return PHPExcel_Calculation_Functions :: VALUE();
  338. }
  339. if (($settlement > $maturity) || (! self :: _validFrequency($frequency)) || (($basis < 0) || ($basis > 4)))
  340. {
  341. return PHPExcel_Calculation_Functions :: NaN();
  342. }
  343. switch ($basis)
  344. {
  345. case 3 : // Actual/365
  346. return 365 / $frequency;
  347. case 1 : // Actual/actual
  348. if ($frequency == 1)
  349. {
  350. $daysPerYear = self :: _daysPerYear(PHPExcel_Calculation_DateTime :: YEAR($maturity), $basis);
  351. return ($daysPerYear / $frequency);
  352. }
  353. else
  354. {
  355. $prev = self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, False);
  356. $next = self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, True);
  357. return ($next - $prev);
  358. }
  359. default : // US (NASD) 30/360, Actual/360 or European 30/360
  360. return 360 / $frequency;
  361. }
  362. return PHPExcel_Calculation_Functions :: VALUE();
  363. } // function COUPDAYS()
  364. public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis = 0)
  365. {
  366. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  367. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  368. $frequency = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  369. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  370. if (is_string($settlement = PHPExcel_Calculation_DateTime :: _getDateValue($settlement)))
  371. {
  372. return PHPExcel_Calculation_Functions :: VALUE();
  373. }
  374. if (is_string($maturity = PHPExcel_Calculation_DateTime :: _getDateValue($maturity)))
  375. {
  376. return PHPExcel_Calculation_Functions :: VALUE();
  377. }
  378. if (($settlement > $maturity) || (! self :: _validFrequency($frequency)) || (($basis < 0) || ($basis > 4)))
  379. {
  380. return PHPExcel_Calculation_Functions :: NaN();
  381. }
  382. $daysPerYear = self :: _daysPerYear(PHPExcel_Calculation_DateTime :: YEAR($settlement), $basis);
  383. $next = self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, True);
  384. return PHPExcel_Calculation_DateTime :: YEARFRAC($settlement, $next, $basis) * $daysPerYear;
  385. } // function COUPDAYSNC()
  386. public static function COUPNCD($settlement, $maturity, $frequency, $basis = 0)
  387. {
  388. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  389. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  390. $frequency = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  391. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  392. if (is_string($settlement = PHPExcel_Calculation_DateTime :: _getDateValue($settlement)))
  393. {
  394. return PHPExcel_Calculation_Functions :: VALUE();
  395. }
  396. if (is_string($maturity = PHPExcel_Calculation_DateTime :: _getDateValue($maturity)))
  397. {
  398. return PHPExcel_Calculation_Functions :: VALUE();
  399. }
  400. if (($settlement > $maturity) || (! self :: _validFrequency($frequency)) || (($basis < 0) || ($basis > 4)))
  401. {
  402. return PHPExcel_Calculation_Functions :: NaN();
  403. }
  404. return self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, True);
  405. } // function COUPNCD()
  406. public static function COUPNUM($settlement, $maturity, $frequency, $basis = 0)
  407. {
  408. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  409. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  410. $frequency = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  411. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  412. if (is_string($settlement = PHPExcel_Calculation_DateTime :: _getDateValue($settlement)))
  413. {
  414. return PHPExcel_Calculation_Functions :: VALUE();
  415. }
  416. if (is_string($maturity = PHPExcel_Calculation_DateTime :: _getDateValue($maturity)))
  417. {
  418. return PHPExcel_Calculation_Functions :: VALUE();
  419. }
  420. if (($settlement > $maturity) || (! self :: _validFrequency($frequency)) || (($basis < 0) || ($basis > 4)))
  421. {
  422. return PHPExcel_Calculation_Functions :: NaN();
  423. }
  424. $settlement = self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, True);
  425. $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime :: YEARFRAC($settlement, $maturity, $basis) * 365;
  426. switch ($frequency)
  427. {
  428. case 1 : // annual payments
  429. return ceil($daysBetweenSettlementAndMaturity / 360);
  430. case 2 : // half-yearly
  431. return ceil($daysBetweenSettlementAndMaturity / 180);
  432. case 4 : // quarterly
  433. return ceil($daysBetweenSettlementAndMaturity / 90);
  434. case 6 : // bimonthly
  435. return ceil($daysBetweenSettlementAndMaturity / 60);
  436. case 12 : // monthly
  437. return ceil($daysBetweenSettlementAndMaturity / 30);
  438. }
  439. return PHPExcel_Calculation_Functions :: VALUE();
  440. } // function COUPNUM()
  441. public static function COUPPCD($settlement, $maturity, $frequency, $basis = 0)
  442. {
  443. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  444. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  445. $frequency = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($frequency);
  446. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  447. if (is_string($settlement = PHPExcel_Calculation_DateTime :: _getDateValue($settlement)))
  448. {
  449. return PHPExcel_Calculation_Functions :: VALUE();
  450. }
  451. if (is_string($maturity = PHPExcel_Calculation_DateTime :: _getDateValue($maturity)))
  452. {
  453. return PHPExcel_Calculation_Functions :: VALUE();
  454. }
  455. if (($settlement > $maturity) || (! self :: _validFrequency($frequency)) || (($basis < 0) || ($basis > 4)))
  456. {
  457. return PHPExcel_Calculation_Functions :: NaN();
  458. }
  459. return self :: _coupFirstPeriodDate($settlement, $maturity, $frequency, False);
  460. } // function COUPPCD()
  461. /**
  462. * CUMIPMT
  463. *
  464. * Returns the cumulative interest paid on a loan between start_period and end_period.
  465. *
  466. * @param float $rate Interest rate per period
  467. * @param int $nper Number of periods
  468. * @param float $pv Present Value
  469. * @param int start The first period in the calculation.
  470. * Payment periods are numbered beginning with 1.
  471. * @param int end The last period in the calculation.
  472. * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
  473. * @return float
  474. */
  475. public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0)
  476. {
  477. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  478. $nper = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($nper);
  479. $pv = PHPExcel_Calculation_Functions :: flattenSingleValue($pv);
  480. $start = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($start);
  481. $end = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($end);
  482. $type = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($type);
  483. // Validate parameters
  484. if ($type != 0 && $type != 1)
  485. {
  486. return PHPExcel_Calculation_Functions :: NaN();
  487. }
  488. if ($start < 1 || $start > $end)
  489. {
  490. return PHPExcel_Calculation_Functions :: VALUE();
  491. }
  492. // Calculate
  493. $interest = 0;
  494. for($per = $start; $per <= $end; ++ $per)
  495. {
  496. $interest += self :: IPMT($rate, $per, $nper, $pv, 0, $type);
  497. }
  498. return $interest;
  499. } // function CUMIPMT()
  500. /**
  501. * CUMPRINC
  502. *
  503. * Returns the cumulative principal paid on a loan between start_period and end_period.
  504. *
  505. * @param float $rate Interest rate per period
  506. * @param int $nper Number of periods
  507. * @param float $pv Present Value
  508. * @param int start The first period in the calculation.
  509. * Payment periods are numbered beginning with 1.
  510. * @param int end The last period in the calculation.
  511. * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
  512. * @return float
  513. */
  514. public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0)
  515. {
  516. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  517. $nper = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($nper);
  518. $pv = PHPExcel_Calculation_Functions :: flattenSingleValue($pv);
  519. $start = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($start);
  520. $end = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($end);
  521. $type = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($type);
  522. // Validate parameters
  523. if ($type != 0 && $type != 1)
  524. {
  525. return PHPExcel_Calculation_Functions :: NaN();
  526. }
  527. if ($start < 1 || $start > $end)
  528. {
  529. return PHPExcel_Calculation_Functions :: VALUE();
  530. }
  531. // Calculate
  532. $principal = 0;
  533. for($per = $start; $per <= $end; ++ $per)
  534. {
  535. $principal += self :: PPMT($rate, $per, $nper, $pv, 0, $type);
  536. }
  537. return $principal;
  538. } // function CUMPRINC()
  539. /**
  540. * DB
  541. *
  542. * Returns the depreciation of an asset for a specified period using the fixed-declining balance method.
  543. * This form of depreciation is used if you want to get a higher depreciation value at the beginning of the depreciation
  544. * (as opposed to linear depreciation). The depreciation value is reduced with every depreciation period by the
  545. * depreciation already deducted from the initial cost.
  546. *
  547. * @param float cost Initial cost of the asset.
  548. * @param float salvage Value at the end of the depreciation. (Sometimes called the salvage value of the asset)
  549. * @param int life Number of periods over which the asset is depreciated. (Sometimes called the useful life of the asset)
  550. * @param int period The period for which you want to calculate the depreciation. Period must use the same units as life.
  551. * @param float month Number of months in the first year. If month is omitted, it defaults to 12.
  552. * @return float
  553. */
  554. public static function DB($cost, $salvage, $life, $period, $month = 12)
  555. {
  556. $cost = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($cost);
  557. $salvage = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($salvage);
  558. $life = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($life);
  559. $period = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($period);
  560. $month = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($month);
  561. // Validate
  562. if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($month)))
  563. {
  564. if ($cost == 0)
  565. {
  566. return 0.0;
  567. }
  568. elseif (($cost < 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($month < 1))
  569. {
  570. return PHPExcel_Calculation_Functions :: NaN();
  571. }
  572. // Set Fixed Depreciation Rate
  573. $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
  574. $fixedDepreciationRate = round($fixedDepreciationRate, 3);
  575. // Loop through each period calculating the depreciation
  576. $previousDepreciation = 0;
  577. for($per = 1; $per <= $period; ++ $per)
  578. {
  579. if ($per == 1)
  580. {
  581. $depreciation = $cost * $fixedDepreciationRate * $month / 12;
  582. }
  583. elseif ($per == ($life + 1))
  584. {
  585. $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12;
  586. }
  587. else
  588. {
  589. $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate;
  590. }
  591. $previousDepreciation += $depreciation;
  592. }
  593. if (PHPExcel_Calculation_Functions :: getCompatibilityMode() == PHPExcel_Calculation_Functions :: COMPATIBILITY_GNUMERIC)
  594. {
  595. $depreciation = round($depreciation, 2);
  596. }
  597. return $depreciation;
  598. }
  599. return PHPExcel_Calculation_Functions :: VALUE();
  600. } // function DB()
  601. /**
  602. * DDB
  603. *
  604. * Returns the depreciation of an asset for a specified period using the double-declining balance method or some other method you specify.
  605. *
  606. * @param float cost Initial cost of the asset.
  607. * @param float salvage Value at the end of the depreciation. (Sometimes called the salvage value of the asset)
  608. * @param int life Number of periods over which the asset is depreciated. (Sometimes called the useful life of the asset)
  609. * @param int period The period for which you want to calculate the depreciation. Period must use the same units as life.
  610. * @param float factor The rate at which the balance declines.
  611. * If factor is omitted, it is assumed to be 2 (the double-declining balance method).
  612. * @return float
  613. */
  614. public static function DDB($cost, $salvage, $life, $period, $factor = 2.0)
  615. {
  616. $cost = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($cost);
  617. $salvage = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($salvage);
  618. $life = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($life);
  619. $period = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($period);
  620. $factor = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($factor);
  621. // Validate
  622. if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($factor)))
  623. {
  624. if (($cost <= 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($factor <= 0.0) || ($period > $life))
  625. {
  626. return PHPExcel_Calculation_Functions :: NaN();
  627. }
  628. // Set Fixed Depreciation Rate
  629. $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
  630. $fixedDepreciationRate = round($fixedDepreciationRate, 3);
  631. // Loop through each period calculating the depreciation
  632. $previousDepreciation = 0;
  633. for($per = 1; $per <= $period; ++ $per)
  634. {
  635. $depreciation = min(($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation));
  636. $previousDepreciation += $depreciation;
  637. }
  638. if (PHPExcel_Calculation_Functions :: getCompatibilityMode() == PHPExcel_Calculation_Functions :: COMPATIBILITY_GNUMERIC)
  639. {
  640. $depreciation = round($depreciation, 2);
  641. }
  642. return $depreciation;
  643. }
  644. return PHPExcel_Calculation_Functions :: VALUE();
  645. } // function DDB()
  646. /**
  647. * DISC
  648. *
  649. * Returns the discount rate for a security.
  650. *
  651. * @param mixed settlement The security's settlement date.
  652. * The security settlement date is the date after the issue date when the security is traded to the buyer.
  653. * @param mixed maturity The security's maturity date.
  654. * The maturity date is the date when the security expires.
  655. * @param int price The security's price per $100 face value.
  656. * @param int redemption the security's redemption value per $100 face value.
  657. * @param int basis The type of day count to use.
  658. * 0 or omitted US (NASD) 30/360
  659. * 1 Actual/actual
  660. * 2 Actual/360
  661. * 3 Actual/365
  662. * 4 European 30/360
  663. * @return float
  664. */
  665. public static function DISC($settlement, $maturity, $price, $redemption, $basis = 0)
  666. {
  667. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  668. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  669. $price = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($price);
  670. $redemption = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($redemption);
  671. $basis = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  672. // Validate
  673. if ((is_numeric($price)) && (is_numeric($redemption)) && (is_numeric($basis)))
  674. {
  675. if (($price <= 0) || ($redemption <= 0))
  676. {
  677. return PHPExcel_Calculation_Functions :: NaN();
  678. }
  679. $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime :: YEARFRAC($settlement, $maturity, $basis);
  680. if (! is_numeric($daysBetweenSettlementAndMaturity))
  681. {
  682. // return date error
  683. return $daysBetweenSettlementAndMaturity;
  684. }
  685. return ((1 - $price / $redemption) / $daysBetweenSettlementAndMaturity);
  686. }
  687. return PHPExcel_Calculation_Functions :: VALUE();
  688. } // function DISC()
  689. /**
  690. * DOLLARDE
  691. *
  692. * Converts a dollar price expressed as an integer part and a fraction part into a dollar price expressed as a decimal number.
  693. * Fractional dollar numbers are sometimes used for security prices.
  694. *
  695. * @param float $fractional_dollar Fractional Dollar
  696. * @param int $fraction Fraction
  697. * @return float
  698. */
  699. public static function DOLLARDE($fractional_dollar = Null, $fraction = 0)
  700. {
  701. $fractional_dollar = PHPExcel_Calculation_Functions :: flattenSingleValue($fractional_dollar);
  702. $fraction = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($fraction);
  703. // Validate parameters
  704. if (is_null($fractional_dollar) || $fraction < 0)
  705. {
  706. return PHPExcel_Calculation_Functions :: NaN();
  707. }
  708. if ($fraction == 0)
  709. {
  710. return PHPExcel_Calculation_Functions :: DIV0();
  711. }
  712. $dollars = floor($fractional_dollar);
  713. $cents = fmod($fractional_dollar, 1);
  714. $cents /= $fraction;
  715. $cents *= pow(10, ceil(log10($fraction)));
  716. return $dollars + $cents;
  717. } // function DOLLARDE()
  718. /**
  719. * DOLLARFR
  720. *
  721. * Converts a dollar price expressed as a decimal number into a dollar price expressed as a fraction.
  722. * Fractional dollar numbers are sometimes used for security prices.
  723. *
  724. * @param float $decimal_dollar Decimal Dollar
  725. * @param int $fraction Fraction
  726. * @return float
  727. */
  728. public static function DOLLARFR($decimal_dollar = Null, $fraction = 0)
  729. {
  730. $decimal_dollar = PHPExcel_Calculation_Functions :: flattenSingleValue($decimal_dollar);
  731. $fraction = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($fraction);
  732. // Validate parameters
  733. if (is_null($decimal_dollar) || $fraction < 0)
  734. {
  735. return PHPExcel_Calculation_Functions :: NaN();
  736. }
  737. if ($fraction == 0)
  738. {
  739. return PHPExcel_Calculation_Functions :: DIV0();
  740. }
  741. $dollars = floor($decimal_dollar);
  742. $cents = fmod($decimal_dollar, 1);
  743. $cents *= $fraction;
  744. $cents *= pow(10, - ceil(log10($fraction)));
  745. return $dollars + $cents;
  746. } // function DOLLARFR()
  747. /**
  748. * EFFECT
  749. *
  750. * Returns the effective interest rate given the nominal rate and the number of compounding payments per year.
  751. *
  752. * @param float $nominal_rate Nominal interest rate
  753. * @param int $npery Number of compounding payments per year
  754. * @return float
  755. */
  756. public static function EFFECT($nominal_rate = 0, $npery = 0)
  757. {
  758. $nominal_rate = PHPExcel_Calculation_Functions :: flattenSingleValue($nominal_rate);
  759. $npery = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($npery);
  760. // Validate parameters
  761. if ($nominal_rate <= 0 || $npery < 1)
  762. {
  763. return PHPExcel_Calculation_Functions :: NaN();
  764. }
  765. return pow((1 + $nominal_rate / $npery), $npery) - 1;
  766. } // function EFFECT()
  767. /**
  768. * FV
  769. *
  770. * Returns the Future Value of a cash flow with constant payments and interest rate (annuities).
  771. *
  772. * @param float $rate Interest rate per period
  773. * @param int $nper Number of periods
  774. * @param float $pmt Periodic payment (annuity)
  775. * @param float $pv Present Value
  776. * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
  777. * @return float
  778. */
  779. public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0)
  780. {
  781. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  782. $nper = PHPExcel_Calculation_Functions :: flattenSingleValue($nper);
  783. $pmt = PHPExcel_Calculation_Functions :: flattenSingleValue($pmt);
  784. $pv = PHPExcel_Calculation_Functions :: flattenSingleValue($pv);
  785. $type = PHPExcel_Calculation_Functions :: flattenSingleValue($type);
  786. // Validate parameters
  787. if ($type != 0 && $type != 1)
  788. {
  789. return PHPExcel_Calculation_Functions :: NaN();
  790. }
  791. // Calculate
  792. if (! is_null($rate) && $rate != 0)
  793. {
  794. return - $pv * pow(1 + $rate, $nper) - $pmt * (1 + $rate * $type) * (pow(1 + $rate, $nper) - 1) / $rate;
  795. }
  796. else
  797. {
  798. return - $pv - $pmt * $nper;
  799. }
  800. } // function FV()
  801. /**
  802. * FVSCHEDULE
  803. *
  804. */
  805. public static function FVSCHEDULE($principal, $schedule)
  806. {
  807. $principal = PHPExcel_Calculation_Functions :: flattenSingleValue($principal);
  808. $schedule = PHPExcel_Calculation_Functions :: flattenArray($schedule);
  809. foreach ($schedule as $n)
  810. {
  811. $principal *= 1 + $n;
  812. }
  813. return $principal;
  814. } // function FVSCHEDULE()
  815. /**
  816. * INTRATE
  817. *
  818. * Returns the interest rate for a fully invested security.
  819. *
  820. * @param mixed settlement The security's settlement date.
  821. * The security settlement date is the date after the issue date when the security is traded to the buyer.
  822. * @param mixed maturity The security's maturity date.
  823. * The maturity date is the date when the security expires.
  824. * @param int investment The amount invested in the security.
  825. * @param int redemption The amount to be received at maturity.
  826. * @param int basis The type of day count to use.
  827. * 0 or omitted US (NASD) 30/360
  828. * 1 Actual/actual
  829. * 2 Actual/360
  830. * 3 Actual/365
  831. * 4 European 30/360
  832. * @return float
  833. */
  834. public static function INTRATE($settlement, $maturity, $investment, $redemption, $basis = 0)
  835. {
  836. $settlement = PHPExcel_Calculation_Functions :: flattenSingleValue($settlement);
  837. $maturity = PHPExcel_Calculation_Functions :: flattenSingleValue($maturity);
  838. $investment = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($investment);
  839. $redemption = (float) PHPExcel_Calculation_Functions :: flattenSingleValue($redemption);
  840. $basis = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($basis);
  841. // Validate
  842. if ((is_numeric($investment)) && (is_numeric($redemption)) && (is_numeric($basis)))
  843. {
  844. if (($investment <= 0) || ($redemption <= 0))
  845. {
  846. return PHPExcel_Calculation_Functions :: NaN();
  847. }
  848. $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime :: YEARFRAC($settlement, $maturity, $basis);
  849. if (! is_numeric($daysBetweenSettlementAndMaturity))
  850. {
  851. // return date error
  852. return $daysBetweenSettlementAndMaturity;
  853. }
  854. return (($redemption / $investment) - 1) / ($daysBetweenSettlementAndMaturity);
  855. }
  856. return PHPExcel_Calculation_Functions :: VALUE();
  857. } // function INTRATE()
  858. /**
  859. * IPMT
  860. *
  861. * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate.
  862. *
  863. * @param float $rate Interest rate per period
  864. * @param int $per Period for which we want to find the interest
  865. * @param int $nper Number of periods
  866. * @param float $pv Present Value
  867. * @param float $fv Future Value
  868. * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
  869. * @return float
  870. */
  871. public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0)
  872. {
  873. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  874. $per = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($per);
  875. $nper = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($nper);
  876. $pv = PHPExcel_Calculation_Functions :: flattenSingleValue($pv);
  877. $fv = PHPExcel_Calculation_Functions :: flattenSingleValue($fv);
  878. $type = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($type);
  879. // Validate parameters
  880. if ($type != 0 && $type != 1)
  881. {
  882. return PHPExcel_Calculation_Functions :: NaN();
  883. }
  884. if ($per <= 0 || $per > $nper)
  885. {
  886. return PHPExcel_Calculation_Functions :: VALUE();
  887. }
  888. // Calculate
  889. $interestAndPrincipal = self :: _interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type);
  890. return $interestAndPrincipal[0];
  891. } // function IPMT()
  892. public static function IRR($values, $guess = 0.1)
  893. {
  894. if (! is_array($values))
  895. return PHPExcel_Calculation_Functions :: VALUE();
  896. $values = PHPExcel_Calculation_Functions :: flattenArray($values);
  897. $guess = PHPExcel_Calculation_Functions :: flattenSingleValue($guess);
  898. // create an initial range, with a root somewhere between 0 and guess
  899. $x1 = 0.0;
  900. $x2 = $guess;
  901. $f1 = self :: NPV($x1, $values);
  902. $f2 = self :: NPV($x2, $values);
  903. for($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++ $i)
  904. {
  905. if (($f1 * $f2) < 0.0)
  906. break;
  907. if (abs($f1) < abs($f2))
  908. {
  909. $f1 = self :: NPV($x1 += 1.6 * ($x1 - $x2), $values);
  910. }
  911. else
  912. {
  913. $f2 = self :: NPV($x2 += 1.6 * ($x2 - $x1), $values);
  914. }
  915. }
  916. if (($f1 * $f2) > 0.0)
  917. return PHPExcel_Calculation_Functions :: VALUE();
  918. $f = self :: NPV($x1, $values);
  919. if ($f < 0.0)
  920. {
  921. $rtb = $x1;
  922. $dx = $x2 - $x1;
  923. }
  924. else
  925. {
  926. $rtb = $x2;
  927. $dx = $x1 - $x2;
  928. }
  929. for($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++ $i)
  930. {
  931. $dx *= 0.5;
  932. $x_mid = $rtb + $dx;
  933. $f_mid = self :: NPV($x_mid, $values);
  934. if ($f_mid <= 0.0)
  935. $rtb = $x_mid;
  936. if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION))
  937. return $x_mid;
  938. }
  939. return PHPExcel_Calculation_Functions :: VALUE();
  940. } // function IRR()
  941. /**
  942. * ISPMT
  943. *
  944. * Returns the interest payment for an investment based on an interest rate and a constant payment schedule.
  945. *
  946. * Excel Function:
  947. * =ISPMT(interest_rate, period, number_payments, PV)
  948. *
  949. * interest_rate is the interest rate for the investment
  950. *
  951. * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments.
  952. *
  953. * number_payments is the number of payments for the annuity
  954. *
  955. * PV is the loan amount or present value of the payments
  956. */
  957. public static function ISPMT()
  958. {
  959. // Return value
  960. $returnValue = 0;
  961. // Get the parameters
  962. $aArgs = PHPExcel_Calculation_Functions :: flattenArray(func_get_args());
  963. $interestRate = array_shift($aArgs);
  964. $period = array_shift($aArgs);
  965. $numberPeriods = array_shift($aArgs);
  966. $principleRemaining = array_shift($aArgs);
  967. // Calculate
  968. $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0);
  969. for($i = 0; $i <= $period; ++ $i)
  970. {
  971. $returnValue = $interestRate * $principleRemaining * - 1;
  972. $principleRemaining -= $principlePayment;
  973. // principle needs to be 0 after the last payment, don't let floating point screw it up
  974. if ($i == $numberPeriods)
  975. {
  976. $returnValue = 0;
  977. }
  978. }
  979. return ($returnValue);
  980. } // function ISPMT()
  981. public static function MIRR($values, $finance_rate, $reinvestment_rate)
  982. {
  983. if (! is_array($values))
  984. return PHPExcel_Calculation_Functions :: VALUE();
  985. $values = PHPExcel_Calculation_Functions :: flattenArray($values);
  986. $finance_rate = PHPExcel_Calculation_Functions :: flattenSingleValue($finance_rate);
  987. $reinvestment_rate = PHPExcel_Calculation_Functions :: flattenSingleValue($reinvestment_rate);
  988. $n = count($values);
  989. $rr = 1.0 + $reinvestment_rate;
  990. $fr = 1.0 + $finance_rate;
  991. $npv_pos = $npv_neg = 0.0;
  992. foreach ($values as $i => $v)
  993. {
  994. if ($v >= 0)
  995. {
  996. $npv_pos += $v / pow($rr, $i);
  997. }
  998. else
  999. {
  1000. $npv_neg += $v / pow($fr, $i);
  1001. }
  1002. }
  1003. if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= - 1))
  1004. {
  1005. return PHPExcel_Calculation_Functions :: VALUE();
  1006. }
  1007. $mirr = pow((- $npv_pos * pow($rr, $n)) / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0;
  1008. return (is_finite($mirr) ? $mirr : PHPExcel_Calculation_Functions :: VALUE());
  1009. } // function MIRR()
  1010. /**
  1011. * NOMINAL
  1012. *
  1013. * Returns the nominal interest rate given the effective rate and the number of compounding payments per year.
  1014. *
  1015. * @param float $effect_rate Effective interest rate
  1016. * @param int $npery Number of compounding payments per year
  1017. * @return float
  1018. */
  1019. public static function NOMINAL($effect_rate = 0, $npery = 0)
  1020. {
  1021. $effect_rate = PHPExcel_Calculation_Functions :: flattenSingleValue($effect_rate);
  1022. $npery = (int) PHPExcel_Calculation_Functions :: flattenSingleValue($npery);
  1023. // Validate parameters
  1024. if ($effect_rate <= 0 || $npery < 1)
  1025. {
  1026. return PHPExcel_Calculation_Functions :: NaN();
  1027. }
  1028. // Calculate
  1029. return $npery * (pow($effect_rate + 1, 1 / $npery) - 1);
  1030. } // function NOMINAL()
  1031. /**
  1032. * NPER
  1033. *
  1034. * Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate.
  1035. *
  1036. * @param float $rate Interest rate per period
  1037. * @param int $pmt Periodic payment (annuity)
  1038. * @param float $pv Present Value
  1039. * @param float $fv Future Value
  1040. * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
  1041. * @return float
  1042. */
  1043. public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0)
  1044. {
  1045. $rate = PHPExcel_Calculation_Functions :: flattenSingleValue($rate);
  1046. $pmt = PHPExcel_Calculation_Functions :: flattenSingleValue($pmt);
  1047. $pv = PHPExcel_Calculation_Functions :: flattenSingleValue($pv);
  1048. $fv = PHPExcel_Calculation_Functions :: flattenSingleValue($fv);
  1049. $type = PHPExcel_Calculation_Functions :: flattenSingleValue($type);
  1050. // Validate parameters
  1051. if ($type != 0 && $type != 1)
  1052. {
  1053. return PHPExcel_Calculation_Functions :: NaN();
  1054. }
  1055. // Calculate
  1056. if (! is_null($rate) && $rate != 0)
  1057. {
  1058. if ($pmt == 0 && $pv == 0)
  1059. {
  1060. return PHPExcel_Calculation_Functions :: NaN();
  1061. }
  1062. return log(($pmt * (1 + $rate * $type) / $rate - $fv) / ($pv + $pmt * (1 + $rate * $type) / $rate)) / log(1 + $rate);
  1063. }
  1064. else
  1065. {
  1066. if ($pmt == 0)
  1067. {
  1068. return PHPExcel_Calculation_Functions :: NaN();
  1069. }
  1070. return (- $pv - $fv) / $pmt;
  1071. }
  1072. } // function NPER()
  1073. /**
  1074. * NPV
  1075. *
  1076. * Returns the Net Present Value of a cash flow series given a discount rate.
  1077. *
  1078. * @param float Discount interest rate
  1079. * @param array Cash flow series
  1080. * @return float
  1081. */
  1082. public static function NPV()
  1083. {
  1084. // Return value
  1085. $returnValue = 0;
  1086. // Loop through arguments
  1087. $aArgs = PHPExcel_Calculation_Functions :: flattenArray(func_get_args());
  1088. // Calculate
  1089. $rate = array_shift($aArgs);
  1090. for($i = 1; $i <= count($aArgs); ++ $i)
  1091. {
  1092. // Is it a numeric value?
  1093. if (is_numeric($aArgs[$i - 1]))
  1094. {
  1095. $returnValue += $aArgs[$i - 1] / pow(1 + $rate, $i);
  1096. }
  1097. }
  1098. // Return
  1099. return $returnValue;
  1100. } // function NPV()
  1101. /**
  1102. * PMT
  1103. *
  1104. * Returns the constant payment (annuity) for a cash flow with a constant interest rate.

Large files files are truncated, but you can click here to view the full file