Initial implementation of the MS Excel RANDARRAY() MathTrig function (#2540)

* Initial implementation of the MS Excel RANDARRAY() MathTrig function
Update Change Log

* Unit Tests for RANDARRAY()
This commit is contained in:
Mark Baker 2022-01-31 22:29:03 +01:00 committed by GitHub
parent 26079174a0
commit ebeed87db5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 118 additions and 2 deletions

View File

@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Added
- Support for the Excel365 Math/Trig SEQUENCE() function [PR #2536](https://github.com/PHPOffice/PhpSpreadsheet/pull/2536)
- Support for the Excel365 Math/Trig SEQUENCE() function [PR #2536](https://github.com/PHPOffice/PhpSpreadsheet/pull/2536)
- Support for the Excel365 Math/Trig RANDARRAY() function [PR #2540](https://github.com/PHPOffice/PhpSpreadsheet/pull/2540)
Note that the Spill Operator is not yet supported in the Calculation Engine; but this can still be useful for defining array constants.
- Improved support for Conditional Formatting Rules [PR #2491](https://github.com/PHPOffice/PhpSpreadsheet/pull/2491)

View File

@ -2078,7 +2078,7 @@ class Calculation
],
'RANDARRAY' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [Functions::class, 'DUMMY'],
'functionCall' => [MathTrig\Random::class, 'randArray'],
'argumentCount' => '0-5',
],
'RANDBETWEEN' => [

View File

@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
class Random
{
@ -36,4 +37,52 @@ class Random
return mt_rand($min, $max);
}
/**
* RANDARRAY.
*
* Generates a list of sequential numbers in an array.
*
* Excel Function:
* RANDARRAY([rows],[columns],[start],[step])
*
* @param mixed $rows the number of rows to return, defaults to 1
* @param mixed $columns the number of columns to return, defaults to 1
* @param mixed $min the minimum number to be returned, defaults to 0
* @param mixed $max the maximum number to be returned, defaults to 1
* @param bool $wholeNumber the type of numbers to return:
* False - Decimal numbers to 15 decimal places. (default)
* True - Whole (integer) numbers
*
* @return array|string The resulting array, or a string containing an error
*/
public static function randArray($rows = 1, $columns = 1, $min = 0, $max = 1, $wholeNumber = false)
{
try {
$rows = (int) Helpers::validateNumericNullSubstitution($rows, 1);
Helpers::validatePositive($rows);
$columns = (int) Helpers::validateNumericNullSubstitution($columns, 1);
Helpers::validatePositive($columns);
$min = Helpers::validateNumericNullSubstitution($min, 1);
$max = Helpers::validateNumericNullSubstitution($max, 1);
if ($max <= $min) {
return Functions::VALUE();
}
} catch (Exception $e) {
return $e->getMessage();
}
return array_chunk(
array_map(
function () use ($min, $max, $wholeNumber) {
return $wholeNumber
? mt_rand((int) $min, (int) $max)
: (mt_rand() / mt_getrandmax()) * ($max - $min) + $min;
},
array_fill(0, $rows * $columns, $min)
),
$columns
);
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
class RandArrayTest extends AllSetupTeardown
{
public function testRANDARRAYInteger(): void
{
$rows = 3;
$cols = 2;
$min = -5;
$max = 5;
$result = MathTrig\Random::randArray($rows, $cols, $min, $max, true);
self::assertIsArray($result);
self::assertCount($rows, $result);
self::assertIsArray($result[0]);
self::assertCount($cols, $result[0]);
$values = Functions::flattenArray($result);
array_walk(
$values,
function ($value) use ($min, $max): void {
self::assertIsInt($value);
self::assertTrue($value >= $min && $value <= $max);
}
);
}
public function testRANDARRAYFloat(): void
{
$rows = 3;
$cols = 2;
$min = -2;
$max = 2;
$result = MathTrig\Random::randArray($rows, $cols, $min, $max, false);
self::assertIsArray($result);
self::assertCount($rows, $result);
self::assertIsArray($result[0]);
self::assertCount($cols, $result[0]);
$values = Functions::flattenArray($result);
array_walk(
$values,
function ($value) use ($min, $max): void {
self::assertIsFloat($value);
self::assertTrue($value >= $min && $value <= $max);
}
);
}
public function testRANDARRAYException(): void
{
$rows = 3;
$cols = 2;
$min = 2;
$max = -2;
$result = MathTrig\Random::randArray($rows, $cols, $min, $max, false);
self::assertSame(Functions::VALUE(), $result);
}
}