From c5c816a9c6303135d50272ea160eed7d992d7dde Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Sun, 13 Feb 2011 17:08:00 +0000 Subject: [PATCH] Feature: Work Item 2346 - Implement more Excel calculation functions Implemented the DAVERAGE(), DCOUNT(), DCOUNTA(), DMAX(), DMIN(), DPRODUCT(), DSTDEV(), DSTDEVP(), DSUM(), DVAR() and DVARP() Database functions git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@68574 2327b42d-5241-43d6-9e2a-de5ac946f064 --- Classes/PHPExcel/Calculation.php | 20 +- Classes/PHPExcel/Calculation/Database.php | 358 ++++++++++++++++++++++ Documentation/FunctionListByCategory.txt | 22 +- Documentation/FunctionListByName.txt | 22 +- changelog.txt | 2 + 5 files changed, 392 insertions(+), 32 deletions(-) create mode 100644 Classes/PHPExcel/Calculation/Database.php diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index 7e839cd0..ccaa7823 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -559,11 +559,11 @@ class PHPExcel_Calculation { 'argumentCount' => '4,5' ), 'DCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DCOUNT', 'argumentCount' => '3' ), 'DCOUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DCOUNTA', 'argumentCount' => '3' ), 'DDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -603,11 +603,11 @@ class PHPExcel_Calculation { 'argumentCount' => '4,5' ), 'DMAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DMAX', 'argumentCount' => '3' ), 'DMIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DMIN', 'argumentCount' => '3' ), 'DOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, @@ -623,19 +623,19 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'DPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DPRODUCT', 'argumentCount' => '3' ), 'DSTDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DSTDEV', 'argumentCount' => '3' ), 'DSTDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DSTDEVP', 'argumentCount' => '3' ), 'DSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DSUM', 'argumentCount' => '3' ), 'DURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -643,11 +643,11 @@ class PHPExcel_Calculation { 'argumentCount' => '5,6' ), 'DVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DVAR', 'argumentCount' => '3' ), 'DVARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Database::DVARP', 'argumentCount' => '3' ), 'EDATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, diff --git a/Classes/PHPExcel/Calculation/Database.php b/Classes/PHPExcel/Calculation/Database.php new file mode 100644 index 00000000..3e267a33 --- /dev/null +++ b/Classes/PHPExcel/Calculation/Database.php @@ -0,0 +1,358 @@ + $criteriaName) { + $testCondition = array(); + $testConditionCount = 0; + foreach($criteria as $row => $criterion) { + if ($criterion[$key] > '') { + $testCondition[] = '[:'.$criteriaName.']'.PHPExcel_Calculation_Functions::_ifCondition($criterion[$key]); + $testConditionCount++; + } + } + if ($testConditionCount > 1) { + $testConditions[] = 'OR('.implode(',',$testCondition).')'; + $testConditionsCount++; + } elseif($testConditionCount == 1) { + $testConditions[] = $testCondition[0]; + $testConditionsCount++; + } + } + if ($testConditionsCount > 1) { + $testConditionSet = 'AND('.implode(',',$testConditions).')'; + } elseif($testConditionsCount == 1) { + $testConditionSet = $testConditions[0]; + } + + // Loop through each row of the database + foreach($database as $dataRow => $dataValues) { + // Substitute actual values from the database row for our [:placeholders] + $testConditionList = $testConditionSet; + foreach($criteriaNames as $key => $criteriaName) { + $k = array_search($criteriaName,$fieldNames); + if (isset($dataValues[$k])) { + $dataValue = $dataValues[$k]; + $dataValue = (is_string($dataValue)) ? PHPExcel_Calculation::_wrapResult(strtoupper($dataValue)) : $dataValue; + $testConditionList = str_replace('[:'.$criteriaName.']',$dataValue,$testConditionList); + } + } + // evaluate the criteria against the row data + $result = PHPExcel_Calculation::getInstance()->_calculateFormulaValue('='.$testConditionList); + // If the row failed to meet the criteria, remove it from the database + if (!$result) { + unset($database[$dataRow]); + } + } + + return $database; + } + + + /** + * DAVERAGE + * + */ + public static function DAVERAGE($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::AVERAGE($colData); + } // function DAVERAGE() + + /** + * DCOUNT + * + */ + public static function DCOUNT($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::COUNT($colData); + } // function DCOUNT() + + /** + * DCOUNTA + * + */ + public static function DCOUNTA($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::COUNTA($colData); + } // function DCOUNTA() + + /** + * DMAX + * + */ + public static function DMAX($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::MAX($colData); + } // function DMAX() + + /** + * DMIN + * + */ + public static function DMIN($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::MIN($colData); + } // function DMIN() + + /** + * DPRODUCT + * + */ + public static function DPRODUCT($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_MathTrig::PRODUCT($colData); + } // function DPRODUCT() + + /** + * DSTDEV + * + */ + public static function DSTDEV($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::STDEV($colData); + } // function DSTDEV() + + /** + * DSTDEVP + * + */ + public static function DSTDEVP($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::STDEVP($colData); + } // function DSTDEVP() + + /** + * DSUM + * + */ + public static function DSUM($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_MathTrig::SUM($colData); + } // function DSUM() + + /** + * DVAR + * + */ + public static function DVAR($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::VARFunc($colData); + } // function DVAR() + + /** + * DVARP + * + */ + public static function DVARP($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::VARP($colData); + } // function DVARP() + + +} // class PHPExcel_Calculation_Database diff --git a/Documentation/FunctionListByCategory.txt b/Documentation/FunctionListByCategory.txt index bc840579..97884c11 100644 --- a/Documentation/FunctionListByCategory.txt +++ b/Documentation/FunctionListByCategory.txt @@ -8,18 +8,18 @@ CATEGORY_CUBE CUBEVALUE *** Not yet Implemented CATEGORY_DATABASE - DAVERAGE *** Not yet Implemented - DCOUNT *** Not yet Implemented - DCOUNTA *** Not yet Implemented + DAVERAGE PHPExcel_Calculation_Database::DAVERAGE + DCOUNT PHPExcel_Calculation_Database::DCOUNT + DCOUNTA PHPExcel_Calculation_Database::DCOUNTA DGET *** Not yet Implemented - DMAX *** Not yet Implemented - DMIN *** Not yet Implemented - DPRODUCT *** Not yet Implemented - DSTDEV *** Not yet Implemented - DSTDEVP *** Not yet Implemented - DSUM *** Not yet Implemented - DVAR *** Not yet Implemented - DVARP *** Not yet Implemented + DMAX PHPExcel_Calculation_Database::DMAX + DMIN PHPExcel_Calculation_Database::DMIN + DPRODUCT PHPExcel_Calculation_Database::DPRODUCT + DSTDEV PHPExcel_Calculation_Database::DSTDEV + DSTDEVP PHPExcel_Calculation_Database::DSTDEVP + DSUM PHPExcel_Calculation_Database::DSUM + DVAR PHPExcel_Calculation_Database::DVAR + DVARP PHPExcel_Calculation_Database::DVARP CATEGORY_DATE_AND_TIME DATE PHPExcel_Calculation_DateTime::DATE diff --git a/Documentation/FunctionListByName.txt b/Documentation/FunctionListByName.txt index 6b17edb0..ff80d4b0 100644 --- a/Documentation/FunctionListByName.txt +++ b/Documentation/FunctionListByName.txt @@ -77,12 +77,12 @@ CUMPRINC CATEGORY_FINANCIAL PHPExcel_Calculation_Fin DATE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATE DATEDIF CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATEDIF DATEVALUE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATEVALUE -DAVERAGE CATEGORY_DATABASE *** Not yet Implemented +DAVERAGE CATEGORY_DATABASE PHPExcel_Calculation_Database::DAVERAGE DAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DAYOFMONTH DAYS360 CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DAYS360 DB CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DB -DCOUNT CATEGORY_DATABASE *** Not yet Implemented -DCOUNTA CATEGORY_DATABASE *** Not yet Implemented +DCOUNT CATEGORY_DATABASE PHPExcel_Calculation_Database::DCOUNT +DCOUNTA CATEGORY_DATABASE PHPExcel_Calculation_Database::DCOUNTA DDB CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DDB DEC2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::DECTOBIN DEC2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::DECTOHEX @@ -92,18 +92,18 @@ DELTA CATEGORY_ENGINEERING PHPExcel_Calculation_Eng DEVSQ CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::DEVSQ DGET CATEGORY_DATABASE *** Not yet Implemented DISC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DISC -DMAX CATEGORY_DATABASE *** Not yet Implemented -DMIN CATEGORY_DATABASE *** Not yet Implemented +DMAX CATEGORY_DATABASE PHPExcel_Calculation_Database::DMAX +DMIN CATEGORY_DATABASE PHPExcel_Calculation_Database::DMIN DOLLAR CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::DOLLAR DOLLARDE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DOLLARDE DOLLARFR CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DOLLARFR -DPRODUCT CATEGORY_DATABASE *** Not yet Implemented -DSTDEV CATEGORY_DATABASE *** Not yet Implemented -DSTDEVP CATEGORY_DATABASE *** Not yet Implemented -DSUM CATEGORY_DATABASE *** Not yet Implemented +DPRODUCT CATEGORY_DATABASE PHPExcel_Calculation_Database::DPRODUCT +DSTDEV CATEGORY_DATABASE PHPExcel_Calculation_Database::DSTDEV +DSTDEVP CATEGORY_DATABASE PHPExcel_Calculation_Database::DSTDEVP +DSUM CATEGORY_DATABASE PHPExcel_Calculation_Database::DSUM DURATION CATEGORY_FINANCIAL *** Not yet Implemented -DVAR CATEGORY_DATABASE *** Not yet Implemented -DVARP CATEGORY_DATABASE *** Not yet Implemented +DVAR CATEGORY_DATABASE PHPExcel_Calculation_Database::DVAR +DVARP CATEGORY_DATABASE PHPExcel_Calculation_Database::DVARP EDATE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::EDATE EFFECT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::EFFECT diff --git a/changelog.txt b/changelog.txt index 66dc2dbc..6f0de4f3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -35,6 +35,8 @@ Fixed in SVN: Modified the toArray() method so that it actually uses rangeToArray(). - Feature: (MBaker) Added support for cell comments in the OOCalc, Gnumeric and Excel2003XML Readers, and in the Excel5 Reader - Feature: (MBaker) Improved toFormattedString() handling for Currency and Accounting formats to render currency symbols +- Feature: (MBaker) Work Item 2346 - Implement more Excel calculation functions + - Implemented the DAVERAGE(), DCOUNT(), DCOUNTA(), DMAX(), DMIN(), DPRODUCT(), DSTDEV(), DSTDEVP(), DSUM(), DVAR() and DVARP() Database functions - Bugfix: (MBaker) Work item 14888 - Simple =IF() formula disappears - Bugfix: (MBaker) Work item 14898 - PHP Warning: preg_match(): Compilation failed: PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X - Bugfix: (MBaker) Work item 14901 - VLOOKUP choking on parameters in PHPExcel.1.7.5/PHPExcel_Writer_Excel2007