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.

676 lines
32 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_Database
  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_Database
  36. {
  37. /**
  38. * fieldExtract
  39. *
  40. * Extracts the column ID to use for the data field.
  41. *
  42. * @access private
  43. * @param mixed[] $database The range of cells that makes up the list or database.
  44. * A database is a list of related data in which rows of related
  45. * information are records, and columns of data are fields. The
  46. * first row of the list contains labels for each column.
  47. * @param mixed $field Indicates which column is used in the function. Enter the
  48. * column label enclosed between double quotation marks, such as
  49. * "Age" or "Yield," or a number (without quotation marks) that
  50. * represents the position of the column within the list: 1 for
  51. * the first column, 2 for the second column, and so on.
  52. * @return string|NULL
  53. *
  54. */
  55. private static function fieldExtract($database, $field)
  56. {
  57. $field = strtoupper(PHPExcel_Calculation_Functions::flattenSingleValue($field));
  58. $fieldNames = array_map('strtoupper', array_shift($database));
  59. if (is_numeric($field)) {
  60. $keys = array_keys($fieldNames);
  61. return $keys[$field-1];
  62. }
  63. $key = array_search($field, $fieldNames);
  64. return ($key) ? $key : null;
  65. }
  66. /**
  67. * filter
  68. *
  69. * Parses the selection criteria, extracts the database rows that match those criteria, and
  70. * returns that subset of rows.
  71. *
  72. * @access private
  73. * @param mixed[] $database The range of cells that makes up the list or database.
  74. * A database is a list of related data in which rows of related
  75. * information are records, and columns of data are fields. The
  76. * first row of the list contains labels for each column.
  77. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  78. * You can use any range for the criteria argument, as long as it
  79. * includes at least one column label and at least one cell below
  80. * the column label in which you specify a condition for the
  81. * column.
  82. * @return array of mixed
  83. *
  84. */
  85. private static function filter($database, $criteria)
  86. {
  87. $fieldNames = array_shift($database);
  88. $criteriaNames = array_shift($criteria);
  89. // Convert the criteria into a set of AND/OR conditions with [:placeholders]
  90. $testConditions = $testValues = array();
  91. $testConditionsCount = 0;
  92. foreach ($criteriaNames as $key => $criteriaName) {
  93. $testCondition = array();
  94. $testConditionCount = 0;
  95. foreach ($criteria as $row => $criterion) {
  96. if ($criterion[$key] > '') {
  97. $testCondition[] = '[:'.$criteriaName.']'.PHPExcel_Calculation_Functions::ifCondition($criterion[$key]);
  98. $testConditionCount++;
  99. }
  100. }
  101. if ($testConditionCount > 1) {
  102. $testConditions[] = 'OR(' . implode(',', $testCondition) . ')';
  103. $testConditionsCount++;
  104. } elseif ($testConditionCount == 1) {
  105. $testConditions[] = $testCondition[0];
  106. $testConditionsCount++;
  107. }
  108. }
  109. if ($testConditionsCount > 1) {
  110. $testConditionSet = 'AND(' . implode(',', $testConditions) . ')';
  111. } elseif ($testConditionsCount == 1) {
  112. $testConditionSet = $testConditions[0];
  113. }
  114. // Loop through each row of the database
  115. foreach ($database as $dataRow => $dataValues) {
  116. // Substitute actual values from the database row for our [:placeholders]
  117. $testConditionList = $testConditionSet;
  118. foreach ($criteriaNames as $key => $criteriaName) {
  119. $k = array_search($criteriaName, $fieldNames);
  120. if (isset($dataValues[$k])) {
  121. $dataValue = $dataValues[$k];
  122. $dataValue = (is_string($dataValue)) ? PHPExcel_Calculation::wrapResult(strtoupper($dataValue)) : $dataValue;
  123. $testConditionList = str_replace('[:' . $criteriaName . ']', $dataValue, $testConditionList);
  124. }
  125. }
  126. // evaluate the criteria against the row data
  127. $result = PHPExcel_Calculation::getInstance()->_calculateFormulaValue('='.$testConditionList);
  128. // If the row failed to meet the criteria, remove it from the database
  129. if (!$result) {
  130. unset($database[$dataRow]);
  131. }
  132. }
  133. return $database;
  134. }
  135. private static function getFilteredColumn($database, $field, $criteria)
  136. {
  137. // reduce the database to a set of rows that match all the criteria
  138. $database = self::filter($database, $criteria);
  139. // extract an array of values for the requested column
  140. $colData = array();
  141. foreach ($database as $row) {
  142. $colData[] = $row[$field];
  143. }
  144. return $colData;
  145. }
  146. /**
  147. * DAVERAGE
  148. *
  149. * Averages the values in a column of a list or database that match conditions you specify.
  150. *
  151. * Excel Function:
  152. * DAVERAGE(database,field,criteria)
  153. *
  154. * @access public
  155. * @category Database Functions
  156. * @param mixed[] $database The range of cells that makes up the list or database.
  157. * A database is a list of related data in which rows of related
  158. * information are records, and columns of data are fields. The
  159. * first row of the list contains labels for each column.
  160. * @param string|integer $field Indicates which column is used in the function. Enter the
  161. * column label enclosed between double quotation marks, such as
  162. * "Age" or "Yield," or a number (without quotation marks) that
  163. * represents the position of the column within the list: 1 for
  164. * the first column, 2 for the second column, and so on.
  165. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  166. * You can use any range for the criteria argument, as long as it
  167. * includes at least one column label and at least one cell below
  168. * the column label in which you specify a condition for the
  169. * column.
  170. * @return float
  171. *
  172. */
  173. public static function DAVERAGE($database, $field, $criteria)
  174. {
  175. $field = self::fieldExtract($database, $field);
  176. if (is_null($field)) {
  177. return null;
  178. }
  179. // Return
  180. return PHPExcel_Calculation_Statistical::AVERAGE(
  181. self::getFilteredColumn($database, $field, $criteria)
  182. );
  183. }
  184. /**
  185. * DCOUNT
  186. *
  187. * Counts the cells that contain numbers in a column of a list or database that match conditions
  188. * that you specify.
  189. *
  190. * Excel Function:
  191. * DCOUNT(database,[field],criteria)
  192. *
  193. * Excel Function:
  194. * DAVERAGE(database,field,criteria)
  195. *
  196. * @access public
  197. * @category Database Functions
  198. * @param mixed[] $database The range of cells that makes up the list or database.
  199. * A database is a list of related data in which rows of related
  200. * information are records, and columns of data are fields. The
  201. * first row of the list contains labels for each column.
  202. * @param string|integer $field Indicates which column is used in the function. Enter the
  203. * column label enclosed between double quotation marks, such as
  204. * "Age" or "Yield," or a number (without quotation marks) that
  205. * represents the position of the column within the list: 1 for
  206. * the first column, 2 for the second column, and so on.
  207. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  208. * You can use any range for the criteria argument, as long as it
  209. * includes at least one column label and at least one cell below
  210. * the column label in which you specify a condition for the
  211. * column.
  212. * @return integer
  213. *
  214. * @TODO The field argument is optional. If field is omitted, DCOUNT counts all records in the
  215. * database that match the criteria.
  216. *
  217. */
  218. public static function DCOUNT($database, $field, $criteria)
  219. {
  220. $field = self::fieldExtract($database, $field);
  221. if (is_null($field)) {
  222. return null;
  223. }
  224. // Return
  225. return PHPExcel_Calculation_Statistical::COUNT(
  226. self::getFilteredColumn($database, $field, $criteria)
  227. );
  228. }
  229. /**
  230. * DCOUNTA
  231. *
  232. * Counts the nonblank cells in a column of a list or database that match conditions that you specify.
  233. *
  234. * Excel Function:
  235. * DCOUNTA(database,[field],criteria)
  236. *
  237. * @access public
  238. * @category Database Functions
  239. * @param mixed[] $database The range of cells that makes up the list or database.
  240. * A database is a list of related data in which rows of related
  241. * information are records, and columns of data are fields. The
  242. * first row of the list contains labels for each column.
  243. * @param string|integer $field Indicates which column is used in the function. Enter the
  244. * column label enclosed between double quotation marks, such as
  245. * "Age" or "Yield," or a number (without quotation marks) that
  246. * represents the position of the column within the list: 1 for
  247. * the first column, 2 for the second column, and so on.
  248. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  249. * You can use any range for the criteria argument, as long as it
  250. * includes at least one column label and at least one cell below
  251. * the column label in which you specify a condition for the
  252. * column.
  253. * @return integer
  254. *
  255. * @TODO The field argument is optional. If field is omitted, DCOUNTA counts all records in the
  256. * database that match the criteria.
  257. *
  258. */
  259. public static function DCOUNTA($database, $field, $criteria)
  260. {
  261. $field = self::fieldExtract($database, $field);
  262. if (is_null($field)) {
  263. return null;
  264. }
  265. // reduce the database to a set of rows that match all the criteria
  266. $database = self::filter($database, $criteria);
  267. // extract an array of values for the requested column
  268. $colData = array();
  269. foreach ($database as $row) {
  270. $colData[] = $row[$field];
  271. }
  272. // Return
  273. return PHPExcel_Calculation_Statistical::COUNTA(
  274. self::getFilteredColumn($database, $field, $criteria)
  275. );
  276. }
  277. /**
  278. * DGET
  279. *
  280. * Extracts a single value from a column of a list or database that matches conditions that you
  281. * specify.
  282. *
  283. * Excel Function:
  284. * DGET(database,field,criteria)
  285. *
  286. * @access public
  287. * @category Database Functions
  288. * @param mixed[] $database The range of cells that makes up the list or database.
  289. * A database is a list of related data in which rows of related
  290. * information are records, and columns of data are fields. The
  291. * first row of the list contains labels for each column.
  292. * @param string|integer $field Indicates which column is used in the function. Enter the
  293. * column label enclosed between double quotation marks, such as
  294. * "Age" or "Yield," or a number (without quotation marks) that
  295. * represents the position of the column within the list: 1 for
  296. * the first column, 2 for the second column, and so on.
  297. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  298. * You can use any range for the criteria argument, as long as it
  299. * includes at least one column label and at least one cell below
  300. * the column label in which you specify a condition for the
  301. * column.
  302. * @return mixed
  303. *
  304. */
  305. public static function DGET($database, $field, $criteria)
  306. {
  307. $field = self::fieldExtract($database, $field);
  308. if (is_null($field)) {
  309. return null;
  310. }
  311. // Return
  312. $colData = self::getFilteredColumn($database, $field, $criteria);
  313. if (count($colData) > 1) {
  314. return PHPExcel_Calculation_Functions::NaN();
  315. }
  316. return $colData[0];
  317. }
  318. /**
  319. * DMAX
  320. *
  321. * Returns the largest number in a column of a list or database that matches conditions you that
  322. * specify.
  323. *
  324. * Excel Function:
  325. * DMAX(database,field,criteria)
  326. *
  327. * @access public
  328. * @category Database Functions
  329. * @param mixed[] $database The range of cells that makes up the list or database.
  330. * A database is a list of related data in which rows of related
  331. * information are records, and columns of data are fields. The
  332. * first row of the list contains labels for each column.
  333. * @param string|integer $field Indicates which column is used in the function. Enter the
  334. * column label enclosed between double quotation marks, such as
  335. * "Age" or "Yield," or a number (without quotation marks) that
  336. * represents the position of the column within the list: 1 for
  337. * the first column, 2 for the second column, and so on.
  338. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  339. * You can use any range for the criteria argument, as long as it
  340. * includes at least one column label and at least one cell below
  341. * the column label in which you specify a condition for the
  342. * column.
  343. * @return float
  344. *
  345. */
  346. public static function DMAX($database, $field, $criteria)
  347. {
  348. $field = self::fieldExtract($database, $field);
  349. if (is_null($field)) {
  350. return null;
  351. }
  352. // Return
  353. return PHPExcel_Calculation_Statistical::MAX(
  354. self::getFilteredColumn($database, $field, $criteria)
  355. );
  356. }
  357. /**
  358. * DMIN
  359. *
  360. * Returns the smallest number in a column of a list or database that matches conditions you that
  361. * specify.
  362. *
  363. * Excel Function:
  364. * DMIN(database,field,criteria)
  365. *
  366. * @access public
  367. * @category Database Functions
  368. * @param mixed[] $database The range of cells that makes up the list or database.
  369. * A database is a list of related data in which rows of related
  370. * information are records, and columns of data are fields. The
  371. * first row of the list contains labels for each column.
  372. * @param string|integer $field Indicates which column is used in the function. Enter the
  373. * column label enclosed between double quotation marks, such as
  374. * "Age" or "Yield," or a number (without quotation marks) that
  375. * represents the position of the column within the list: 1 for
  376. * the first column, 2 for the second column, and so on.
  377. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  378. * You can use any range for the criteria argument, as long as it
  379. * includes at least one column label and at least one cell below
  380. * the column label in which you specify a condition for the
  381. * column.
  382. * @return float
  383. *
  384. */
  385. public static function DMIN($database, $field, $criteria)
  386. {
  387. $field = self::fieldExtract($database, $field);
  388. if (is_null($field)) {
  389. return null;
  390. }
  391. // Return
  392. return PHPExcel_Calculation_Statistical::MIN(
  393. self::getFilteredColumn($database, $field, $criteria)
  394. );
  395. }
  396. /**
  397. * DPRODUCT
  398. *
  399. * Multiplies the values in a column of a list or database that match conditions that you specify.
  400. *
  401. * Excel Function:
  402. * DPRODUCT(database,field,criteria)
  403. *
  404. * @access public
  405. * @category Database Functions
  406. * @param mixed[] $database The range of cells that makes up the list or database.
  407. * A database is a list of related data in which rows of related
  408. * information are records, and columns of data are fields. The
  409. * first row of the list contains labels for each column.
  410. * @param string|integer $field Indicates which column is used in the function. Enter the
  411. * column label enclosed between double quotation marks, such as
  412. * "Age" or "Yield," or a number (without quotation marks) that
  413. * represents the position of the column within the list: 1 for
  414. * the first column, 2 for the second column, and so on.
  415. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  416. * You can use any range for the criteria argument, as long as it
  417. * includes at least one column label and at least one cell below
  418. * the column label in which you specify a condition for the
  419. * column.
  420. * @return float
  421. *
  422. */
  423. public static function DPRODUCT($database, $field, $criteria)
  424. {
  425. $field = self::fieldExtract($database, $field);
  426. if (is_null($field)) {
  427. return null;
  428. }
  429. // Return
  430. return PHPExcel_Calculation_MathTrig::PRODUCT(
  431. self::getFilteredColumn($database, $field, $criteria)
  432. );
  433. }
  434. /**
  435. * DSTDEV
  436. *
  437. * Estimates the standard deviation of a population based on a sample by using the numbers in a
  438. * column of a list or database that match conditions that you specify.
  439. *
  440. * Excel Function:
  441. * DSTDEV(database,field,criteria)
  442. *
  443. * @access public
  444. * @category Database Functions
  445. * @param mixed[] $database The range of cells that makes up the list or database.
  446. * A database is a list of related data in which rows of related
  447. * information are records, and columns of data are fields. The
  448. * first row of the list contains labels for each column.
  449. * @param string|integer $field Indicates which column is used in the function. Enter the
  450. * column label enclosed between double quotation marks, such as
  451. * "Age" or "Yield," or a number (without quotation marks) that
  452. * represents the position of the column within the list: 1 for
  453. * the first column, 2 for the second column, and so on.
  454. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  455. * You can use any range for the criteria argument, as long as it
  456. * includes at least one column label and at least one cell below
  457. * the column label in which you specify a condition for the
  458. * column.
  459. * @return float
  460. *
  461. */
  462. public static function DSTDEV($database, $field, $criteria)
  463. {
  464. $field = self::fieldExtract($database, $field);
  465. if (is_null($field)) {
  466. return null;
  467. }
  468. // Return
  469. return PHPExcel_Calculation_Statistical::STDEV(
  470. self::getFilteredColumn($database, $field, $criteria)
  471. );
  472. }
  473. /**
  474. * DSTDEVP
  475. *
  476. * Calculates the standard deviation of a population based on the entire population by using the
  477. * numbers in a column of a list or database that match conditions that you specify.
  478. *
  479. * Excel Function:
  480. * DSTDEVP(database,field,criteria)
  481. *
  482. * @access public
  483. * @category Database Functions
  484. * @param mixed[] $database The range of cells that makes up the list or database.
  485. * A database is a list of related data in which rows of related
  486. * information are records, and columns of data are fields. The
  487. * first row of the list contains labels for each column.
  488. * @param string|integer $field Indicates which column is used in the function. Enter the
  489. * column label enclosed between double quotation marks, such as
  490. * "Age" or "Yield," or a number (without quotation marks) that
  491. * represents the position of the column within the list: 1 for
  492. * the first column, 2 for the second column, and so on.
  493. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  494. * You can use any range for the criteria argument, as long as it
  495. * includes at least one column label and at least one cell below
  496. * the column label in which you specify a condition for the
  497. * column.
  498. * @return float
  499. *
  500. */
  501. public static function DSTDEVP($database, $field, $criteria)
  502. {
  503. $field = self::fieldExtract($database, $field);
  504. if (is_null($field)) {
  505. return null;
  506. }
  507. // Return
  508. return PHPExcel_Calculation_Statistical::STDEVP(
  509. self::getFilteredColumn($database, $field, $criteria)
  510. );
  511. }
  512. /**
  513. * DSUM
  514. *
  515. * Adds the numbers in a column of a list or database that match conditions that you specify.
  516. *
  517. * Excel Function:
  518. * DSUM(database,field,criteria)
  519. *
  520. * @access public
  521. * @category Database Functions
  522. * @param mixed[] $database The range of cells that makes up the list or database.
  523. * A database is a list of related data in which rows of related
  524. * information are records, and columns of data are fields. The
  525. * first row of the list contains labels for each column.
  526. * @param string|integer $field Indicates which column is used in the function. Enter the
  527. * column label enclosed between double quotation marks, such as
  528. * "Age" or "Yield," or a number (without quotation marks) that
  529. * represents the position of the column within the list: 1 for
  530. * the first column, 2 for the second column, and so on.
  531. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  532. * You can use any range for the criteria argument, as long as it
  533. * includes at least one column label and at least one cell below
  534. * the column label in which you specify a condition for the
  535. * column.
  536. * @return float
  537. *
  538. */
  539. public static function DSUM($database, $field, $criteria)
  540. {
  541. $field = self::fieldExtract($database, $field);
  542. if (is_null($field)) {
  543. return null;
  544. }
  545. // Return
  546. return PHPExcel_Calculation_MathTrig::SUM(
  547. self::getFilteredColumn($database, $field, $criteria)
  548. );
  549. }
  550. /**
  551. * DVAR
  552. *
  553. * Estimates the variance of a population based on a sample by using the numbers in a column
  554. * of a list or database that match conditions that you specify.
  555. *
  556. * Excel Function:
  557. * DVAR(database,field,criteria)
  558. *
  559. * @access public
  560. * @category Database Functions
  561. * @param mixed[] $database The range of cells that makes up the list or database.
  562. * A database is a list of related data in which rows of related
  563. * information are records, and columns of data are fields. The
  564. * first row of the list contains labels for each column.
  565. * @param string|integer $field Indicates which column is used in the function. Enter the
  566. * column label enclosed between double quotation marks, such as
  567. * "Age" or "Yield," or a number (without quotation marks) that
  568. * represents the position of the column within the list: 1 for
  569. * the first column, 2 for the second column, and so on.
  570. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  571. * You can use any range for the criteria argument, as long as it
  572. * includes at least one column label and at least one cell below
  573. * the column label in which you specify a condition for the
  574. * column.
  575. * @return float
  576. *
  577. */
  578. public static function DVAR($database, $field, $criteria)
  579. {
  580. $field = self::fieldExtract($database, $field);
  581. if (is_null($field)) {
  582. return null;
  583. }
  584. // Return
  585. return PHPExcel_Calculation_Statistical::VARFunc(
  586. self::getFilteredColumn($database, $field, $criteria)
  587. );
  588. }
  589. /**
  590. * DVARP
  591. *
  592. * Calculates the variance of a population based on the entire population by using the numbers
  593. * in a column of a list or database that match conditions that you specify.
  594. *
  595. * Excel Function:
  596. * DVARP(database,field,criteria)
  597. *
  598. * @access public
  599. * @category Database Functions
  600. * @param mixed[] $database The range of cells that makes up the list or database.
  601. * A database is a list of related data in which rows of related
  602. * information are records, and columns of data are fields. The
  603. * first row of the list contains labels for each column.
  604. * @param string|integer $field Indicates which column is used in the function. Enter the
  605. * column label enclosed between double quotation marks, such as
  606. * "Age" or "Yield," or a number (without quotation marks) that
  607. * represents the position of the column within the list: 1 for
  608. * the first column, 2 for the second column, and so on.
  609. * @param mixed[] $criteria The range of cells that contains the conditions you specify.
  610. * You can use any range for the criteria argument, as long as it
  611. * includes at least one column label and at least one cell below
  612. * the column label in which you specify a condition for the
  613. * column.
  614. * @return float
  615. *
  616. */
  617. public static function DVARP($database, $field, $criteria)
  618. {
  619. $field = self::fieldExtract($database, $field);
  620. if (is_null($field)) {
  621. return null;
  622. }
  623. // Return
  624. return PHPExcel_Calculation_Statistical::VARP(
  625. self::getFilteredColumn($database, $field, $criteria)
  626. );
  627. }
  628. }