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:
parent
26079174a0
commit
ebeed87db5
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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' => [
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue