Continue MathTrig Breakup - Problem Children (#1954)
Continuing the process of breaking MathTrip.php up into smaller classes. This round takes care of all functions which might be an impediment to installing due to either uncovered code or "complexity": - BASE - FACT - LCM - MDETERM, MINVERSE, MMULT - MULTINOMIAL - PRODUCT - QUOTIENT - SERIESSUM - SUM - SUMPRODUCT MathTrig and the members in directory MathTrig are now 100% covered. Many tests have been added, and some edge-case bugs are corrected. Some cases where PhpSpreadsheet had rejected numeric values stored as strings have been changed to accept them whenever Excel does; there had been no tests for that condition. Boolean arguments are now accepted as arguments wherever Excel accpets them. Taking a cue from what has been done in Engineering, the parameter validation now happens in a routine which issues Exceptions for invalid values; this simplifies the code in the functions themselves. Thank you for doing that; I did not foresee how useful that was when I first looked at it. Consistent with earlier changes of this nature, the versions in the MathTrig class remain, with a doc block indicating deprecation, and a stub call to the new routines. All tests except for MINVERSE and MMULT are now handled in the context of a spreadsheet rather than a direct call to the calculation function which implements it. PhpSpreadsheet would need to handle dynamic arrays in order to test MINVERSE and MMULT in a spreadsheet context. Implementing that looks like it might be *very* challenging. It is not something I plan to look at, at least not in the near future. One parsing problem turned up in the test conversion. It is in one of the SUMIF tests. It takes me to an area in Calculation where the comment says "I don't even want to know what you did to get here". It did not show up in the previous incarnation because, by using a direct call, the previous test managed to bypass the parsing. I have confirmed that this problem shows up in earlier releases of PhpSpreadsheet, so the changes in this PR did not cause it - they merely exposed it. I have left the test intact, but marked it "incomplete" for documentation purposes. I have not been able to get a handle on what's going wrong yet. I will probably open an issue on it if I can't resolve it soon. However, the test in question isn't a "real world" issue, and the error wasn't caused by this change, so I see no reason to delay this pending a resolution of the problem. SUM had an idiosyncratic moment of its own. It had been ignoring non-numeric values, but Excel returns VALUE in that situation. So I changed it and wrote some new tests, which worked, but ... SUMIF uses several levels of indirection to get to SUM, and SUMIF *does* ignore non-numeric values, so a SUMIF test broke. SUM is a really simple function; the most practical approach seemed to be to clone it, with the string-accepting version being used by the Legacy version (which is called by SUMIF), and the non-string-accepting version being used in the Calculation Function table. That seems far easier and more practical than, for instance, adding a boolean parameter to the variable parameter list. As a follow-up, I will change SUMIF to explicitly call the appropriate new version, but I did not want to add that to this already large change. SUM again - although it was fully covered beforehand, there was not a specific test member for it. There is now. FACT had been coded to fail Gnumeric requests where the numeric argument has a decimal portion. However, Gnumeric does accept such an argument, and, unlike Excel and ODS, does not truncate it, but returns the result of a Gamma function call instead. This has been corrected. When LCM included arguments which contained both 0 and a negative number, it returned 0 or NUM, whichever it found first. It is changed to always return NUM in that circumstance, as Excel does. QUOTIENT had been documented as taking a variadic list of arguments. In fact, it takes exactly 2 - numerator and denominator - and the docblock and signature is fixed, even in the deprecated version. The SERIESSUM docbock and signature are more accurate, even in the deprecated version. It is changed to ignore nulls, as Excel does, rather than return VALUE, and is one of the routines which previously rejected numbers in string form. SUBTOTAL tests had used mocking for some reason. These are replaced with normal tests. And SUBTOTAL had a big surprise in store. That part of it which deals with hidden cells cares only whether the row is hidden, and doesn't care about the column's visibility. I struggled with whether it should be SubTotal or Subtotal. I think the latter is correct, so that's how I proceeded. I don't think there are likely to be any other capitalization controversies.
This commit is contained in:
parent
c380b25d3c
commit
9239b3deca
|
|
@ -358,7 +358,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'BASE' => [
|
'BASE' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'BASE'],
|
'functionCall' => [MathTrig\Base::class, 'funcBase'],
|
||||||
'argumentCount' => '2,3',
|
'argumentCount' => '2,3',
|
||||||
],
|
],
|
||||||
'BESSELI' => [
|
'BESSELI' => [
|
||||||
|
|
@ -990,7 +990,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'FACT' => [
|
'FACT' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'FACT'],
|
'functionCall' => [MathTrig\Fact::class, 'funcFact'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'FACTDOUBLE' => [
|
'FACTDOUBLE' => [
|
||||||
|
|
@ -1536,7 +1536,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'LCM' => [
|
'LCM' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'LCM'],
|
'functionCall' => [MathTrig\Lcm::class, 'funcLcm'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'LEFT' => [
|
'LEFT' => [
|
||||||
|
|
@ -1636,7 +1636,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'MDETERM' => [
|
'MDETERM' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'MDETERM'],
|
'functionCall' => [MathTrig\MatrixFunctions::class, 'funcMDeterm'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'MDURATION' => [
|
'MDURATION' => [
|
||||||
|
|
@ -1686,7 +1686,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'MINVERSE' => [
|
'MINVERSE' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'MINVERSE'],
|
'functionCall' => [MathTrig\MatrixFunctions::class, 'funcMinverse'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'MIRR' => [
|
'MIRR' => [
|
||||||
|
|
@ -1696,7 +1696,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'MMULT' => [
|
'MMULT' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'MMULT'],
|
'functionCall' => [MathTrig\MatrixFunctions::class, 'funcMMult'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'MOD' => [
|
'MOD' => [
|
||||||
|
|
@ -1731,7 +1731,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'MULTINOMIAL' => [
|
'MULTINOMIAL' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'MULTINOMIAL'],
|
'functionCall' => [MathTrig\Multinomial::class, 'funcMultinomial'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'MUNIT' => [
|
'MUNIT' => [
|
||||||
|
|
@ -2003,7 +2003,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'PRODUCT' => [
|
'PRODUCT' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'PRODUCT'],
|
'functionCall' => [MathTrig\Product::class, 'funcProduct'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'PROPER' => [
|
'PROPER' => [
|
||||||
|
|
@ -2033,7 +2033,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'QUOTIENT' => [
|
'QUOTIENT' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'QUOTIENT'],
|
'functionCall' => [MathTrig\Quotient::class, 'funcQuotient'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'RADIANS' => [
|
'RADIANS' => [
|
||||||
|
|
@ -2305,13 +2305,13 @@ class Calculation
|
||||||
],
|
],
|
||||||
'SUBTOTAL' => [
|
'SUBTOTAL' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'SUBTOTAL'],
|
'functionCall' => [MathTrig\Subtotal::class, 'funcSubtotal'],
|
||||||
'argumentCount' => '2+',
|
'argumentCount' => '2+',
|
||||||
'passCellReference' => true,
|
'passCellReference' => true,
|
||||||
],
|
],
|
||||||
'SUM' => [
|
'SUM' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'SUM'],
|
'functionCall' => [MathTrig\Sum::class, 'funcSumNoStrings'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'SUMIF' => [
|
'SUMIF' => [
|
||||||
|
|
@ -2326,7 +2326,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'SUMPRODUCT' => [
|
'SUMPRODUCT' => [
|
||||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||||
'functionCall' => [MathTrig::class, 'SUMPRODUCT'],
|
'functionCall' => [MathTrig\SumProduct::class, 'funcSumProduct'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'SUMSQ' => [
|
'SUMSQ' => [
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ class Database
|
||||||
* the column label in which you specify a condition for the
|
* the column label in which you specify a condition for the
|
||||||
* column.
|
* column.
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function DPRODUCT($database, $field, $criteria)
|
public static function DPRODUCT($database, $field, $criteria)
|
||||||
{
|
{
|
||||||
|
|
@ -349,7 +349,7 @@ class Database
|
||||||
* the column label in which you specify a condition for the
|
* the column label in which you specify a condition for the
|
||||||
* column.
|
* column.
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function DSUM($database, $field, $criteria)
|
public static function DSUM($database, $field, $criteria)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class DProduct extends DatabaseAbstract
|
||||||
* the column label in which you specify a condition for the
|
* the column label in which you specify a condition for the
|
||||||
* column.
|
* column.
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function evaluate($database, $field, $criteria)
|
public static function evaluate($database, $field, $criteria)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class DSum extends DatabaseAbstract
|
||||||
* the column label in which you specify a condition for the
|
* the column label in which you specify a condition for the
|
||||||
* column.
|
* column.
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function evaluate($database, $field, $criteria)
|
public static function evaluate($database, $field, $criteria)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,37 +3,9 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
namespace PhpOffice\PhpSpreadsheet\Calculation;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Matrix\Exception as MatrixException;
|
|
||||||
use Matrix\Matrix;
|
|
||||||
|
|
||||||
class MathTrig
|
class MathTrig
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// Private method to return an array of the factors of the input value
|
|
||||||
//
|
|
||||||
private static function factors($value)
|
|
||||||
{
|
|
||||||
$startVal = floor(sqrt($value));
|
|
||||||
|
|
||||||
$factorArray = [];
|
|
||||||
for ($i = $startVal; $i > 1; --$i) {
|
|
||||||
if (($value % $i) == 0) {
|
|
||||||
$factorArray = array_merge($factorArray, self::factors($value / $i));
|
|
||||||
$factorArray = array_merge($factorArray, self::factors($i));
|
|
||||||
if ($i <= sqrt($value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($factorArray)) {
|
|
||||||
rsort($factorArray);
|
|
||||||
|
|
||||||
return $factorArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [(int) $value];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function strSplit(string $roman): array
|
private static function strSplit(string $roman): array
|
||||||
{
|
{
|
||||||
$rslt = str_split($roman);
|
$rslt = str_split($roman);
|
||||||
|
|
@ -153,6 +125,8 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Converts a number into a text representation with the given radix (base).
|
* Converts a number into a text representation with the given radix (base).
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcBase method in the MathTrig\Base class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* BASE(Number, Radix [Min_length])
|
* BASE(Number, Radix [Min_length])
|
||||||
*
|
*
|
||||||
|
|
@ -164,29 +138,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function BASE($number, $radix, $minLength = null)
|
public static function BASE($number, $radix, $minLength = null)
|
||||||
{
|
{
|
||||||
$number = Functions::flattenSingleValue($number);
|
return MathTrig\Base::funcBase($number, $radix, $minLength);
|
||||||
$radix = Functions::flattenSingleValue($radix);
|
|
||||||
$minLength = Functions::flattenSingleValue($minLength);
|
|
||||||
|
|
||||||
if (is_numeric($number) && is_numeric($radix) && ($minLength === null || is_numeric($minLength))) {
|
|
||||||
// Truncate to an integer
|
|
||||||
$number = (int) $number;
|
|
||||||
$radix = (int) $radix;
|
|
||||||
$minLength = (int) $minLength;
|
|
||||||
|
|
||||||
if ($number < 0 || $number >= 2 ** 53 || $radix < 2 || $radix > 36) {
|
|
||||||
return Functions::NAN(); // Numeric range constraints
|
|
||||||
}
|
|
||||||
|
|
||||||
$outcome = strtoupper((string) base_convert($number, 10, $radix));
|
|
||||||
if ($minLength !== null) {
|
|
||||||
$outcome = str_pad($outcome, $minLength, '0', STR_PAD_LEFT); // String padding
|
|
||||||
}
|
|
||||||
|
|
||||||
return $outcome;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -240,7 +192,7 @@ class MathTrig
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
|
|
||||||
return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet);
|
return round(MathTrig\Fact::funcFact($numObjs) / MathTrig\Fact::funcFact($numObjs - $numInSet)) / MathTrig\Fact::funcFact($numInSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
|
|
@ -285,6 +237,8 @@ class MathTrig
|
||||||
* Returns the factorial of a number.
|
* Returns the factorial of a number.
|
||||||
* The factorial of a number is equal to 1*2*3*...* number.
|
* The factorial of a number is equal to 1*2*3*...* number.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcFact method in the MathTrig\Fact class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* FACT(factVal)
|
* FACT(factVal)
|
||||||
*
|
*
|
||||||
|
|
@ -294,29 +248,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function FACT($factVal)
|
public static function FACT($factVal)
|
||||||
{
|
{
|
||||||
$factVal = Functions::flattenSingleValue($factVal);
|
return MathTrig\Fact::funcFact($factVal);
|
||||||
|
|
||||||
if (is_numeric($factVal)) {
|
|
||||||
if ($factVal < 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
$factLoop = floor($factVal);
|
|
||||||
if (
|
|
||||||
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) &&
|
|
||||||
($factVal > $factLoop)
|
|
||||||
) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
$factorial = 1;
|
|
||||||
while ($factLoop > 1) {
|
|
||||||
$factorial *= $factLoop--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $factorial;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -487,6 +419,8 @@ class MathTrig
|
||||||
* of all integer arguments number1, number2, and so on. Use LCM to add fractions
|
* of all integer arguments number1, number2, and so on. Use LCM to add fractions
|
||||||
* with different denominators.
|
* with different denominators.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcLcm method in the MathTrig\Lcm class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* LCM(number1[,number2[, ...]])
|
* LCM(number1[,number2[, ...]])
|
||||||
*
|
*
|
||||||
|
|
@ -496,39 +430,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function LCM(...$args)
|
public static function LCM(...$args)
|
||||||
{
|
{
|
||||||
$returnValue = 1;
|
return MathTrig\Lcm::funcLcm(...$args);
|
||||||
$allPoweredFactors = [];
|
|
||||||
// Loop through arguments
|
|
||||||
foreach (Functions::flattenArray($args) as $value) {
|
|
||||||
if (!is_numeric($value)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
if ($value == 0) {
|
|
||||||
return 0;
|
|
||||||
} elseif ($value < 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
$myFactors = self::factors(floor($value));
|
|
||||||
$myCountedFactors = array_count_values($myFactors);
|
|
||||||
$myPoweredFactors = [];
|
|
||||||
foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
|
|
||||||
$myPoweredFactors[$myCountedFactor] = $myCountedFactor ** $myCountedPower;
|
|
||||||
}
|
|
||||||
foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
|
|
||||||
if (isset($allPoweredFactors[$myPoweredValue])) {
|
|
||||||
if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
|
|
||||||
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($allPoweredFactors as $allPoweredFactor) {
|
|
||||||
$returnValue *= (int) $allPoweredFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -564,6 +466,8 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the matrix determinant of an array.
|
* Returns the matrix determinant of an array.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcMDeterm method in the MathTrig\MatrixFuncs class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* MDETERM(array)
|
* MDETERM(array)
|
||||||
*
|
*
|
||||||
|
|
@ -573,40 +477,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function MDETERM($matrixValues)
|
public static function MDETERM($matrixValues)
|
||||||
{
|
{
|
||||||
$matrixData = [];
|
return MathTrig\MatrixFunctions::funcMDeterm($matrixValues);
|
||||||
if (!is_array($matrixValues)) {
|
|
||||||
$matrixValues = [[$matrixValues]];
|
|
||||||
}
|
|
||||||
|
|
||||||
$row = $maxColumn = 0;
|
|
||||||
foreach ($matrixValues as $matrixRow) {
|
|
||||||
if (!is_array($matrixRow)) {
|
|
||||||
$matrixRow = [$matrixRow];
|
|
||||||
}
|
|
||||||
$column = 0;
|
|
||||||
foreach ($matrixRow as $matrixCell) {
|
|
||||||
if ((is_string($matrixCell)) || ($matrixCell === null)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
$matrixData[$row][$column] = $matrixCell;
|
|
||||||
++$column;
|
|
||||||
}
|
|
||||||
if ($column > $maxColumn) {
|
|
||||||
$maxColumn = $column;
|
|
||||||
}
|
|
||||||
++$row;
|
|
||||||
}
|
|
||||||
|
|
||||||
$matrix = new Matrix($matrixData);
|
|
||||||
if (!$matrix->isSquare()) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return $matrix->determinant();
|
|
||||||
} catch (MatrixException $ex) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -614,6 +485,8 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the inverse matrix for the matrix stored in an array.
|
* Returns the inverse matrix for the matrix stored in an array.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcMInverse method in the MathTrig\MatrixFuncs class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* MINVERSE(array)
|
* MINVERSE(array)
|
||||||
*
|
*
|
||||||
|
|
@ -623,49 +496,14 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function MINVERSE($matrixValues)
|
public static function MINVERSE($matrixValues)
|
||||||
{
|
{
|
||||||
$matrixData = [];
|
return MathTrig\MatrixFunctions::funcMInverse($matrixValues);
|
||||||
if (!is_array($matrixValues)) {
|
|
||||||
$matrixValues = [[$matrixValues]];
|
|
||||||
}
|
|
||||||
|
|
||||||
$row = $maxColumn = 0;
|
|
||||||
foreach ($matrixValues as $matrixRow) {
|
|
||||||
if (!is_array($matrixRow)) {
|
|
||||||
$matrixRow = [$matrixRow];
|
|
||||||
}
|
|
||||||
$column = 0;
|
|
||||||
foreach ($matrixRow as $matrixCell) {
|
|
||||||
if ((is_string($matrixCell)) || ($matrixCell === null)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
$matrixData[$row][$column] = $matrixCell;
|
|
||||||
++$column;
|
|
||||||
}
|
|
||||||
if ($column > $maxColumn) {
|
|
||||||
$maxColumn = $column;
|
|
||||||
}
|
|
||||||
++$row;
|
|
||||||
}
|
|
||||||
|
|
||||||
$matrix = new Matrix($matrixData);
|
|
||||||
if (!$matrix->isSquare()) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($matrix->determinant() == 0.0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return $matrix->inverse()->toArray();
|
|
||||||
} catch (MatrixException $ex) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MMULT.
|
* MMULT.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcMMult method in the MathTrig\MatrixFuncs class instead
|
||||||
|
*
|
||||||
* @param array $matrixData1 A matrix of values
|
* @param array $matrixData1 A matrix of values
|
||||||
* @param array $matrixData2 A matrix of values
|
* @param array $matrixData2 A matrix of values
|
||||||
*
|
*
|
||||||
|
|
@ -673,56 +511,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function MMULT($matrixData1, $matrixData2)
|
public static function MMULT($matrixData1, $matrixData2)
|
||||||
{
|
{
|
||||||
$matrixAData = $matrixBData = [];
|
return MathTrig\MatrixFunctions::funcMMult($matrixData1, $matrixData2);
|
||||||
if (!is_array($matrixData1)) {
|
|
||||||
$matrixData1 = [[$matrixData1]];
|
|
||||||
}
|
|
||||||
if (!is_array($matrixData2)) {
|
|
||||||
$matrixData2 = [[$matrixData2]];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$rowA = 0;
|
|
||||||
foreach ($matrixData1 as $matrixRow) {
|
|
||||||
if (!is_array($matrixRow)) {
|
|
||||||
$matrixRow = [$matrixRow];
|
|
||||||
}
|
|
||||||
$columnA = 0;
|
|
||||||
foreach ($matrixRow as $matrixCell) {
|
|
||||||
if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
$matrixAData[$rowA][$columnA] = $matrixCell;
|
|
||||||
++$columnA;
|
|
||||||
}
|
|
||||||
++$rowA;
|
|
||||||
}
|
|
||||||
$matrixA = new Matrix($matrixAData);
|
|
||||||
$rowB = 0;
|
|
||||||
foreach ($matrixData2 as $matrixRow) {
|
|
||||||
if (!is_array($matrixRow)) {
|
|
||||||
$matrixRow = [$matrixRow];
|
|
||||||
}
|
|
||||||
$columnB = 0;
|
|
||||||
foreach ($matrixRow as $matrixCell) {
|
|
||||||
if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
$matrixBData[$rowB][$columnB] = $matrixCell;
|
|
||||||
++$columnB;
|
|
||||||
}
|
|
||||||
++$rowB;
|
|
||||||
}
|
|
||||||
$matrixB = new Matrix($matrixBData);
|
|
||||||
|
|
||||||
if ($columnA != $rowB) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $matrixA->multiply($matrixB)->toArray();
|
|
||||||
} catch (MatrixException $ex) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -779,30 +568,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function MULTINOMIAL(...$args)
|
public static function MULTINOMIAL(...$args)
|
||||||
{
|
{
|
||||||
$summer = 0;
|
return MathTrig\Multinomial::funcMultinomial(...$args);
|
||||||
$divisor = 1;
|
|
||||||
// Loop through arguments
|
|
||||||
foreach (Functions::flattenArray($args) as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if (is_numeric($arg)) {
|
|
||||||
if ($arg < 1) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
$summer += floor($arg);
|
|
||||||
$divisor *= self::FACT($arg);
|
|
||||||
} else {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
if ($summer > 0) {
|
|
||||||
$summer = self::FACT($summer);
|
|
||||||
|
|
||||||
return $summer / $divisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -854,36 +620,18 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* PRODUCT returns the product of all the values and cells referenced in the argument list.
|
* PRODUCT returns the product of all the values and cells referenced in the argument list.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcProduct method in the MathTrig\Product class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* PRODUCT(value1[,value2[, ...]])
|
* PRODUCT(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function PRODUCT(...$args)
|
public static function PRODUCT(...$args)
|
||||||
{
|
{
|
||||||
// Return value
|
return MathTrig\Product::funcProduct(...$args);
|
||||||
$returnValue = null;
|
|
||||||
|
|
||||||
// Loop through arguments
|
|
||||||
foreach (Functions::flattenArray($args) as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
if ($returnValue === null) {
|
|
||||||
$returnValue = $arg;
|
|
||||||
} else {
|
|
||||||
$returnValue *= $arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
if ($returnValue === null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -892,36 +640,19 @@ class MathTrig
|
||||||
* QUOTIENT function returns the integer portion of a division. Numerator is the divided number
|
* QUOTIENT function returns the integer portion of a division. Numerator is the divided number
|
||||||
* and denominator is the divisor.
|
* and denominator is the divisor.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcQuotient method in the MathTrig\Quotient class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* QUOTIENT(value1[,value2[, ...]])
|
* QUOTIENT(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed $numerator
|
||||||
|
* @param mixed $denominator
|
||||||
*
|
*
|
||||||
* @return float
|
* @return int|string
|
||||||
*/
|
*/
|
||||||
public static function QUOTIENT(...$args)
|
public static function QUOTIENT($numerator, $denominator)
|
||||||
{
|
{
|
||||||
// Return value
|
return MathTrig\Quotient::funcQuotient($numerator, $denominator);
|
||||||
$returnValue = null;
|
|
||||||
|
|
||||||
// Loop through arguments
|
|
||||||
foreach (Functions::flattenArray($args) as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
if ($returnValue === null) {
|
|
||||||
$returnValue = ($arg == 0) ? 0 : $arg;
|
|
||||||
} else {
|
|
||||||
if (($returnValue == 0) || ($arg == 0)) {
|
|
||||||
$returnValue = 0;
|
|
||||||
} else {
|
|
||||||
$returnValue /= $arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return (int) $returnValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1006,37 +737,18 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* Returns the sum of a power series
|
* Returns the sum of a power series
|
||||||
*
|
*
|
||||||
* @param mixed[] $args An array of mixed values for the Data Series
|
* @Deprecated 2.0.0 Use the funcSeriesSum method in the MathTrig\SeriesSum class instead
|
||||||
|
*
|
||||||
|
* @param mixed $x Input value
|
||||||
|
* @param mixed $n Initial power
|
||||||
|
* @param mixed $m Step
|
||||||
|
* @param mixed[] $args An array of coefficients for the Data Series
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function SERIESSUM(...$args)
|
public static function SERIESSUM($x, $n, $m, ...$args)
|
||||||
{
|
{
|
||||||
$returnValue = 0;
|
return MathTrig\SeriesSum::funcSeriesSum($x, $n, $m, ...$args);
|
||||||
|
|
||||||
// Loop through arguments
|
|
||||||
$aArgs = Functions::flattenArray($args);
|
|
||||||
|
|
||||||
$x = array_shift($aArgs);
|
|
||||||
$n = array_shift($aArgs);
|
|
||||||
$m = array_shift($aArgs);
|
|
||||||
|
|
||||||
if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) {
|
|
||||||
// Calculate
|
|
||||||
$i = 0;
|
|
||||||
foreach ($aArgs as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$returnValue += $arg * $x ** ($n + ($m * $i++));
|
|
||||||
} else {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1090,45 +802,13 @@ class MathTrig
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function filterHiddenArgs($cellReference, $args)
|
|
||||||
{
|
|
||||||
return array_filter(
|
|
||||||
$args,
|
|
||||||
function ($index) use ($cellReference) {
|
|
||||||
[, $row, $column] = explode('.', $index);
|
|
||||||
|
|
||||||
return $cellReference->getWorksheet()->getRowDimension($row)->getVisible() &&
|
|
||||||
$cellReference->getWorksheet()->getColumnDimension($column)->getVisible();
|
|
||||||
},
|
|
||||||
ARRAY_FILTER_USE_KEY
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function filterFormulaArgs($cellReference, $args)
|
|
||||||
{
|
|
||||||
return array_filter(
|
|
||||||
$args,
|
|
||||||
function ($index) use ($cellReference) {
|
|
||||||
[, $row, $column] = explode('.', $index);
|
|
||||||
if ($cellReference->getWorksheet()->cellExists($column . $row)) {
|
|
||||||
//take this cell out if it contains the SUBTOTAL or AGGREGATE functions in a formula
|
|
||||||
$isFormula = $cellReference->getWorksheet()->getCell($column . $row)->isFormula();
|
|
||||||
$cellFormula = !preg_match('/^=.*\b(SUBTOTAL|AGGREGATE)\s*\(/i', $cellReference->getWorksheet()->getCell($column . $row)->getValue());
|
|
||||||
|
|
||||||
return !$isFormula || $cellFormula;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
ARRAY_FILTER_USE_KEY
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SUBTOTAL.
|
* SUBTOTAL.
|
||||||
*
|
*
|
||||||
* Returns a subtotal in a list or database.
|
* Returns a subtotal in a list or database.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcSubtotal method in the MathTrig\Subtotal class instead
|
||||||
|
*
|
||||||
* @param int $functionType
|
* @param int $functionType
|
||||||
* A number 1 to 11 that specifies which function to
|
* A number 1 to 11 that specifies which function to
|
||||||
* use in calculating subtotals within a range
|
* use in calculating subtotals within a range
|
||||||
|
|
@ -1142,45 +822,7 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function SUBTOTAL($functionType, ...$args)
|
public static function SUBTOTAL($functionType, ...$args)
|
||||||
{
|
{
|
||||||
$cellReference = array_pop($args);
|
return MathTrig\Subtotal::funcSubtotal($functionType, ...$args);
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
|
||||||
$subtotal = Functions::flattenSingleValue($functionType);
|
|
||||||
|
|
||||||
// Calculate
|
|
||||||
if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
|
|
||||||
if ($subtotal > 100) {
|
|
||||||
$aArgs = self::filterHiddenArgs($cellReference, $aArgs);
|
|
||||||
$subtotal -= 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
$aArgs = self::filterFormulaArgs($cellReference, $aArgs);
|
|
||||||
switch ($subtotal) {
|
|
||||||
case 1:
|
|
||||||
return Statistical\Averages::average($aArgs);
|
|
||||||
case 2:
|
|
||||||
return Statistical\Counts::COUNT($aArgs);
|
|
||||||
case 3:
|
|
||||||
return Statistical\Counts::COUNTA($aArgs);
|
|
||||||
case 4:
|
|
||||||
return Statistical\Maximum::MAX($aArgs);
|
|
||||||
case 5:
|
|
||||||
return Statistical\Minimum::MIN($aArgs);
|
|
||||||
case 6:
|
|
||||||
return self::PRODUCT($aArgs);
|
|
||||||
case 7:
|
|
||||||
return Statistical\StandardDeviations::STDEV($aArgs);
|
|
||||||
case 8:
|
|
||||||
return Statistical\StandardDeviations::STDEVP($aArgs);
|
|
||||||
case 9:
|
|
||||||
return self::SUM($aArgs);
|
|
||||||
case 10:
|
|
||||||
return Statistical\Variances::VAR($aArgs);
|
|
||||||
case 11:
|
|
||||||
return Statistical\Variances::VARP($aArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1188,28 +830,18 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* SUM computes the sum of all the values and cells referenced in the argument list.
|
* SUM computes the sum of all the values and cells referenced in the argument list.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcSumNoStrings method in the MathTrig\Sum class instead
|
||||||
|
*
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* SUM(value1[,value2[, ...]])
|
* SUM(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function SUM(...$args)
|
public static function SUM(...$args)
|
||||||
{
|
{
|
||||||
$returnValue = 0;
|
return MathTrig\Sum::funcSum(...$args);
|
||||||
|
|
||||||
// Loop through the arguments
|
|
||||||
foreach (Functions::flattenArray($args) as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$returnValue += $arg;
|
|
||||||
} elseif (Functions::isError($arg)) {
|
|
||||||
return $arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1229,7 +861,7 @@ class MathTrig
|
||||||
* @param string $criteria the criteria that defines which cells will be summed
|
* @param string $criteria the criteria that defines which cells will be summed
|
||||||
* @param mixed $sumRange
|
* @param mixed $sumRange
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function SUMIF($range, $criteria, $sumRange = [])
|
public static function SUMIF($range, $criteria, $sumRange = [])
|
||||||
{
|
{
|
||||||
|
|
@ -1251,7 +883,7 @@ class MathTrig
|
||||||
*
|
*
|
||||||
* @param mixed $args Data values
|
* @param mixed $args Data values
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function SUMIFS(...$args)
|
public static function SUMIFS(...$args)
|
||||||
{
|
{
|
||||||
|
|
@ -1264,39 +896,15 @@ class MathTrig
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* SUMPRODUCT(value1[,value2[, ...]])
|
* SUMPRODUCT(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
|
* @Deprecated 2.0.0 Use the funcSumProduct method in the MathTrig\SumProduct class instead
|
||||||
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function SUMPRODUCT(...$args)
|
public static function SUMPRODUCT(...$args)
|
||||||
{
|
{
|
||||||
$arrayList = $args;
|
return MathTrig\SumProduct::funcSumProduct(...$args);
|
||||||
|
|
||||||
$wrkArray = Functions::flattenArray(array_shift($arrayList));
|
|
||||||
$wrkCellCount = count($wrkArray);
|
|
||||||
|
|
||||||
for ($i = 0; $i < $wrkCellCount; ++$i) {
|
|
||||||
if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) {
|
|
||||||
$wrkArray[$i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($arrayList as $matrixData) {
|
|
||||||
$array2 = Functions::flattenArray($matrixData);
|
|
||||||
$count = count($array2);
|
|
||||||
if ($wrkCellCount != $count) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($array2 as $i => $val) {
|
|
||||||
if ((!is_numeric($val)) || (is_string($val))) {
|
|
||||||
$val = 0;
|
|
||||||
}
|
|
||||||
$wrkArray[$i] *= $val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_sum($wrkArray);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* BASE.
|
||||||
|
*
|
||||||
|
* Converts a number into a text representation with the given radix (base).
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* BASE(Number, Radix [Min_length])
|
||||||
|
*
|
||||||
|
* @param mixed $number expect float
|
||||||
|
* @param mixed $radix expect float
|
||||||
|
* @param mixed $minLength expect int or null
|
||||||
|
*
|
||||||
|
* @return string the text representation with the given radix (base)
|
||||||
|
*/
|
||||||
|
public static function funcBase($number, $radix, $minLength = null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$number = (int) Helpers::validateNumericNullBool($number);
|
||||||
|
$radix = (int) Helpers::validateNumericNullBool($radix);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
$minLength = Functions::flattenSingleValue($minLength);
|
||||||
|
|
||||||
|
if ($minLength === null || is_numeric($minLength)) {
|
||||||
|
if ($number < 0 || $number >= 2 ** 53 || $radix < 2 || $radix > 36) {
|
||||||
|
return Functions::NAN(); // Numeric range constraints
|
||||||
|
}
|
||||||
|
|
||||||
|
$outcome = strtoupper((string) base_convert($number, 10, $radix));
|
||||||
|
if ($minLength !== null) {
|
||||||
|
$outcome = str_pad($outcome, (int) $minLength, '0', STR_PAD_LEFT); // String padding
|
||||||
|
}
|
||||||
|
|
||||||
|
return $outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
|
||||||
|
class Fact
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* FACT.
|
||||||
|
*
|
||||||
|
* Returns the factorial of a number.
|
||||||
|
* The factorial of a number is equal to 1*2*3*...* number.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* FACT(factVal)
|
||||||
|
*
|
||||||
|
* @param float $factVal Factorial Value
|
||||||
|
*
|
||||||
|
* @return int|string Factorial, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcFact($factVal)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$factVal = Helpers::validateNumericNullBool($factVal);
|
||||||
|
Helpers::validateNotNegative($factVal);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$factLoop = floor($factVal);
|
||||||
|
if ($factVal > $factLoop) {
|
||||||
|
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
|
||||||
|
return Statistical::GAMMAFunction($factVal + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$factorial = 1;
|
||||||
|
while ($factLoop > 1) {
|
||||||
|
$factorial *= $factLoop--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $factorial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,6 +61,34 @@ class Helpers
|
||||||
throw new Exception(Functions::VALUE());
|
throw new Exception(Functions::VALUE());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm number >= 0.
|
||||||
|
*
|
||||||
|
* @param float|int $number
|
||||||
|
*/
|
||||||
|
public static function validateNotNegative($number): void
|
||||||
|
{
|
||||||
|
if ($number >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception(Functions::NAN());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm number != 0.
|
||||||
|
*
|
||||||
|
* @param float|int $number
|
||||||
|
*/
|
||||||
|
public static function validateNotZero($number): void
|
||||||
|
{
|
||||||
|
if ($number) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception(Functions::DIV0());
|
||||||
|
}
|
||||||
|
|
||||||
public static function returnSign(float $number): int
|
public static function returnSign(float $number): int
|
||||||
{
|
{
|
||||||
return $number ? (($number > 0) ? 1 : -1) : 0;
|
return $number ? (($number > 0) ? 1 : -1) : 0;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Lcm
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Private method to return an array of the factors of the input value
|
||||||
|
//
|
||||||
|
private static function factors($value)
|
||||||
|
{
|
||||||
|
$startVal = floor(sqrt($value));
|
||||||
|
|
||||||
|
$factorArray = [];
|
||||||
|
for ($i = $startVal; $i > 1; --$i) {
|
||||||
|
if (($value % $i) == 0) {
|
||||||
|
$factorArray = array_merge($factorArray, self::factors($value / $i));
|
||||||
|
$factorArray = array_merge($factorArray, self::factors($i));
|
||||||
|
if ($i <= sqrt($value)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($factorArray)) {
|
||||||
|
rsort($factorArray);
|
||||||
|
|
||||||
|
return $factorArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [(int) $value];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LCM.
|
||||||
|
*
|
||||||
|
* Returns the lowest common multiplier of a series of numbers
|
||||||
|
* The least common multiple is the smallest positive integer that is a multiple
|
||||||
|
* of all integer arguments number1, number2, and so on. Use LCM to add fractions
|
||||||
|
* with different denominators.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* LCM(number1[,number2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return int|string Lowest Common Multiplier, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcLcm(...$args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$arrayArgs = [];
|
||||||
|
$anyZeros = 0;
|
||||||
|
foreach (Functions::flattenArray($args) as $value1) {
|
||||||
|
$value = Helpers::validateNumericNullSubstitution($value1, 1);
|
||||||
|
Helpers::validateNotNegative($value);
|
||||||
|
$arrayArgs[] = (int) $value;
|
||||||
|
$anyZeros += (int) !((bool) $value);
|
||||||
|
}
|
||||||
|
if ($anyZeros) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$returnValue = 1;
|
||||||
|
$allPoweredFactors = [];
|
||||||
|
// Loop through arguments
|
||||||
|
foreach ($arrayArgs as $value) {
|
||||||
|
$myFactors = self::factors(floor($value));
|
||||||
|
$myCountedFactors = array_count_values($myFactors);
|
||||||
|
$myPoweredFactors = [];
|
||||||
|
foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
|
||||||
|
$myPoweredFactors[$myCountedFactor] = $myCountedFactor ** $myCountedPower;
|
||||||
|
}
|
||||||
|
foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
|
||||||
|
if (isset($allPoweredFactors[$myPoweredValue])) {
|
||||||
|
if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
|
||||||
|
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($allPoweredFactors as $allPoweredFactor) {
|
||||||
|
$returnValue *= (int) $allPoweredFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Matrix\Exception as MatrixException;
|
||||||
|
use Matrix\Matrix;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class MatrixFunctions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert parameter to matrix.
|
||||||
|
*
|
||||||
|
* @param mixed $matrixValues A matrix of values
|
||||||
|
*/
|
||||||
|
private static function getMatrix($matrixValues): Matrix
|
||||||
|
{
|
||||||
|
$matrixData = [];
|
||||||
|
if (!is_array($matrixValues)) {
|
||||||
|
$matrixValues = [[$matrixValues]];
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = 0;
|
||||||
|
foreach ($matrixValues as $matrixRow) {
|
||||||
|
if (!is_array($matrixRow)) {
|
||||||
|
$matrixRow = [$matrixRow];
|
||||||
|
}
|
||||||
|
$column = 0;
|
||||||
|
foreach ($matrixRow as $matrixCell) {
|
||||||
|
if ((is_string($matrixCell)) || ($matrixCell === null)) {
|
||||||
|
throw new Exception(Functions::VALUE());
|
||||||
|
}
|
||||||
|
$matrixData[$row][$column] = $matrixCell;
|
||||||
|
++$column;
|
||||||
|
}
|
||||||
|
++$row;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Matrix($matrixData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MDETERM.
|
||||||
|
*
|
||||||
|
* Returns the matrix determinant of an array.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* MDETERM(array)
|
||||||
|
*
|
||||||
|
* @param mixed $matrixValues A matrix of values
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcMDeterm($matrixValues)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$matrix = self::getMatrix($matrixValues);
|
||||||
|
|
||||||
|
return $matrix->determinant();
|
||||||
|
} catch (MatrixException $ex) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MINVERSE.
|
||||||
|
*
|
||||||
|
* Returns the inverse matrix for the matrix stored in an array.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* MINVERSE(array)
|
||||||
|
*
|
||||||
|
* @param mixed $matrixValues A matrix of values
|
||||||
|
*
|
||||||
|
* @return array|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcMInverse($matrixValues)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$matrix = self::getMatrix($matrixValues);
|
||||||
|
|
||||||
|
return $matrix->inverse()->toArray();
|
||||||
|
} catch (MatrixException $e) {
|
||||||
|
return (strpos($e->getMessage(), 'determinant') === false) ? Functions::VALUE() : Functions::NAN();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MMULT.
|
||||||
|
*
|
||||||
|
* @param mixed $matrixData1 A matrix of values
|
||||||
|
* @param mixed $matrixData2 A matrix of values
|
||||||
|
*
|
||||||
|
* @return array|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcMMult($matrixData1, $matrixData2)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$matrixA = self::getMatrix($matrixData1);
|
||||||
|
$matrixB = self::getMatrix($matrixData2);
|
||||||
|
|
||||||
|
return $matrixA->multiply($matrixB)->toArray();
|
||||||
|
} catch (MatrixException $ex) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Multinomial
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* MULTINOMIAL.
|
||||||
|
*
|
||||||
|
* Returns the ratio of the factorial of a sum of values to the product of factorials.
|
||||||
|
*
|
||||||
|
* @param mixed[] $args An array of mixed values for the Data Series
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcMultinomial(...$args)
|
||||||
|
{
|
||||||
|
$summer = 0;
|
||||||
|
$divisor = 1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Loop through arguments
|
||||||
|
foreach (Functions::flattenArray($args) as $argx) {
|
||||||
|
$arg = Helpers::validateNumericNullSubstitution($argx, null);
|
||||||
|
Helpers::validateNotNegative($arg);
|
||||||
|
$arg = (int) $arg;
|
||||||
|
$summer += $arg;
|
||||||
|
$divisor *= Fact::funcFact($arg);
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$summer = Fact::funcFact($summer);
|
||||||
|
|
||||||
|
return $summer / $divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Product
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* PRODUCT.
|
||||||
|
*
|
||||||
|
* PRODUCT returns the product of all the values and cells referenced in the argument list.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* PRODUCT(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function funcProduct(...$args)
|
||||||
|
{
|
||||||
|
// Return value
|
||||||
|
$returnValue = null;
|
||||||
|
|
||||||
|
// Loop through arguments
|
||||||
|
foreach (Functions::flattenArray($args) as $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if (is_numeric($arg)) {
|
||||||
|
if ($returnValue === null) {
|
||||||
|
$returnValue = $arg;
|
||||||
|
} else {
|
||||||
|
$returnValue *= $arg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
if ($returnValue === null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class Quotient
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* QUOTIENT.
|
||||||
|
*
|
||||||
|
* QUOTIENT function returns the integer portion of a division. Numerator is the divided number
|
||||||
|
* and denominator is the divisor.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* QUOTIENT(value1,value2)
|
||||||
|
*
|
||||||
|
* @param mixed $numerator Expect float|int
|
||||||
|
* @param mixed $denominator Expect float|int
|
||||||
|
*
|
||||||
|
* @return int|string
|
||||||
|
*/
|
||||||
|
public static function funcQuotient($numerator, $denominator)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$numerator = Helpers::validateNumericNullSubstitution($numerator, 0);
|
||||||
|
$denominator = Helpers::validateNumericNullSubstitution($denominator, 0);
|
||||||
|
Helpers::validateNotZero($denominator);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) ($numerator / $denominator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class SeriesSum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SERIESSUM.
|
||||||
|
*
|
||||||
|
* Returns the sum of a power series
|
||||||
|
*
|
||||||
|
* @param mixed $x Input value
|
||||||
|
* @param mixed $n Initial power
|
||||||
|
* @param mixed $m Step
|
||||||
|
* @param mixed[] $args An array of coefficients for the Data Series
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcSeriesSum($x, $n, $m, ...$args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$x = Helpers::validateNumericNullSubstitution($x, 0);
|
||||||
|
$n = Helpers::validateNumericNullSubstitution($n, 0);
|
||||||
|
$m = Helpers::validateNumericNullSubstitution($m, 0);
|
||||||
|
|
||||||
|
// Loop through arguments
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
$returnValue = 0;
|
||||||
|
$i = 0;
|
||||||
|
foreach ($aArgs as $argx) {
|
||||||
|
if ($argx !== null) {
|
||||||
|
$arg = Helpers::validateNumericNullSubstitution($argx, 0);
|
||||||
|
$returnValue += $arg * $x ** ($n + ($m * $i));
|
||||||
|
++$i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
|
||||||
|
class Subtotal
|
||||||
|
{
|
||||||
|
protected static function filterHiddenArgs($cellReference, $args)
|
||||||
|
{
|
||||||
|
return array_filter(
|
||||||
|
$args,
|
||||||
|
function ($index) use ($cellReference) {
|
||||||
|
[, $row, ] = explode('.', $index);
|
||||||
|
|
||||||
|
return $cellReference->getWorksheet()->getRowDimension($row)->getVisible();
|
||||||
|
},
|
||||||
|
ARRAY_FILTER_USE_KEY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function filterFormulaArgs($cellReference, $args)
|
||||||
|
{
|
||||||
|
return array_filter(
|
||||||
|
$args,
|
||||||
|
function ($index) use ($cellReference) {
|
||||||
|
[, $row, $column] = explode('.', $index);
|
||||||
|
$retVal = true;
|
||||||
|
if ($cellReference->getWorksheet()->cellExists($column . $row)) {
|
||||||
|
//take this cell out if it contains the SUBTOTAL or AGGREGATE functions in a formula
|
||||||
|
$isFormula = $cellReference->getWorksheet()->getCell($column . $row)->isFormula();
|
||||||
|
$cellFormula = !preg_match('/^=.*\b(SUBTOTAL|AGGREGATE)\s*\(/i', $cellReference->getWorksheet()->getCell($column . $row)->getValue());
|
||||||
|
|
||||||
|
$retVal = !$isFormula || $cellFormula;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $retVal;
|
||||||
|
},
|
||||||
|
ARRAY_FILTER_USE_KEY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const CALL_FUNCTIONS = [
|
||||||
|
1 => [Statistical\Averages::class, 'AVERAGE'],
|
||||||
|
[Statistical\Counts::class, 'COUNT'], // 2
|
||||||
|
[Statistical\Counts::class, 'COUNTA'], // 3
|
||||||
|
[Statistical\Maximum::class, 'MAX'], // 4
|
||||||
|
[Statistical\Minimum::class, 'MIN'], // 5
|
||||||
|
[Product::class, 'funcProduct'], // 6
|
||||||
|
[Statistical\StandardDeviations::class, 'STDEV'], // 7
|
||||||
|
[Statistical\StandardDeviations::class, 'STDEVP'], // 8
|
||||||
|
[Sum::class, 'funcSum'], // 9
|
||||||
|
[Statistical\Variances::class, 'VAR'], // 10
|
||||||
|
[Statistical\Variances::class, 'VARP'], // 11
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SUBTOTAL.
|
||||||
|
*
|
||||||
|
* Returns a subtotal in a list or database.
|
||||||
|
*
|
||||||
|
* @param mixed $functionType
|
||||||
|
* A number 1 to 11 that specifies which function to
|
||||||
|
* use in calculating subtotals within a range
|
||||||
|
* list
|
||||||
|
* Numbers 101 to 111 shadow the functions of 1 to 11
|
||||||
|
* but ignore any values in the range that are
|
||||||
|
* in hidden rows or columns
|
||||||
|
* @param mixed[] $args A mixed data series of values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function funcSubtotal($functionType, ...$args)
|
||||||
|
{
|
||||||
|
$cellReference = array_pop($args);
|
||||||
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$subtotal = (int) Helpers::validateNumericNullBool($functionType);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate
|
||||||
|
if ($subtotal > 100) {
|
||||||
|
$aArgs = self::filterHiddenArgs($cellReference, $aArgs);
|
||||||
|
$subtotal -= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aArgs = self::filterFormulaArgs($cellReference, $aArgs);
|
||||||
|
if (array_key_exists($subtotal, self::CALL_FUNCTIONS)) {
|
||||||
|
return call_user_func_array(self::CALL_FUNCTIONS[$subtotal], $aArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Sum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SUM, ignoring non-numeric non-error strings. This is eventually used by SUMIF.
|
||||||
|
*
|
||||||
|
* SUM computes the sum of all the values and cells referenced in the argument list.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* SUM(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function funcSum(...$args)
|
||||||
|
{
|
||||||
|
$returnValue = 0;
|
||||||
|
|
||||||
|
// Loop through the arguments
|
||||||
|
foreach (Functions::flattenArray($args) as $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if (is_numeric($arg)) {
|
||||||
|
$returnValue += $arg;
|
||||||
|
} elseif (Functions::isError($arg)) {
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SUM, returning error for non-numeric strings. This is used by Excel SUM function.
|
||||||
|
*
|
||||||
|
* SUM computes the sum of all the values and cells referenced in the argument list.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* SUM(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function funcSumNoStrings(...$args)
|
||||||
|
{
|
||||||
|
$returnValue = 0;
|
||||||
|
|
||||||
|
// Loop through the arguments
|
||||||
|
foreach (Functions::flattenArray($args) as $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if (is_numeric($arg)) {
|
||||||
|
$returnValue += $arg;
|
||||||
|
} elseif (Functions::isError($arg)) {
|
||||||
|
return $arg;
|
||||||
|
} else {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class SumProduct
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SUMPRODUCT.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* SUMPRODUCT(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function funcSumProduct(...$args)
|
||||||
|
{
|
||||||
|
$arrayList = $args;
|
||||||
|
|
||||||
|
$wrkArray = Functions::flattenArray(array_shift($arrayList));
|
||||||
|
$wrkCellCount = count($wrkArray);
|
||||||
|
|
||||||
|
for ($i = 0; $i < $wrkCellCount; ++$i) {
|
||||||
|
if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) {
|
||||||
|
$wrkArray[$i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($arrayList as $matrixData) {
|
||||||
|
$array2 = Functions::flattenArray($matrixData);
|
||||||
|
$count = count($array2);
|
||||||
|
if ($wrkCellCount != $count) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($array2 as $i => $val) {
|
||||||
|
if ((!is_numeric($val)) || (is_string($val))) {
|
||||||
|
$val = 0;
|
||||||
|
}
|
||||||
|
$wrkArray[$i] *= $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_sum($wrkArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -178,7 +178,7 @@ class Conditional
|
||||||
* @param mixed $sumRange
|
* @param mixed $sumRange
|
||||||
* @param mixed $condition
|
* @param mixed $condition
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function SUMIF($range, $condition, $sumRange = [])
|
public static function SUMIF($range, $condition, $sumRange = [])
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AcosTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AcosTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerAcos
|
* @dataProvider providerAcos
|
||||||
|
|
@ -15,11 +11,8 @@ class AcosTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testAcos($expectedResult, string $formula): void
|
public function testAcos($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue(0.5);
|
$sheet->getCell('A2')->setValue(0.5);
|
||||||
$sheet->getCell('A1')->setValue("=ACOS($formula)");
|
$sheet->getCell('A1')->setValue("=ACOS($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AcoshTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AcoshTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerAcosh
|
* @dataProvider providerAcosh
|
||||||
|
|
@ -15,11 +11,8 @@ class AcoshTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testAcosh($expectedResult, string $formula): void
|
public function testAcosh($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue('1.5');
|
$sheet->getCell('A2')->setValue('1.5');
|
||||||
$sheet->getCell('A1')->setValue("=ACOSH($formula)");
|
$sheet->getCell('A1')->setValue("=ACOSH($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AcotTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AcotTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerACOT
|
* @dataProvider providerACOT
|
||||||
|
|
@ -16,11 +12,8 @@ class AcotTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testACOT($expectedResult, $number): void
|
public function testACOT($expectedResult, $number): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AcothTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AcothTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerACOTH
|
* @dataProvider providerACOTH
|
||||||
|
|
@ -16,11 +12,8 @@ class AcothTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testACOTH($expectedResult, $number): void
|
public function testACOTH($expectedResult, $number): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcException;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class AllSetupTeardown extends TestCase
|
||||||
|
{
|
||||||
|
protected $compatibilityMode;
|
||||||
|
|
||||||
|
protected $spreadsheet;
|
||||||
|
|
||||||
|
protected $sheet;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->compatibilityMode = Functions::getCompatibilityMode();
|
||||||
|
$this->spreadsheet = new Spreadsheet();
|
||||||
|
$this->sheet = $this->spreadsheet->getActiveSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Functions::setCompatibilityMode($this->compatibilityMode);
|
||||||
|
$this->spreadsheet->disconnectWorksheets();
|
||||||
|
$this->spreadsheet = null;
|
||||||
|
$this->sheet = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function setOpenOffice(): void
|
||||||
|
{
|
||||||
|
Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function setGnumeric(): void
|
||||||
|
{
|
||||||
|
Functions::setCompatibilityMode(Functions::COMPATIBILITY_GNUMERIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
*/
|
||||||
|
protected function mightHaveException($expectedResult): void
|
||||||
|
{
|
||||||
|
if ($expectedResult === 'exception') {
|
||||||
|
$this->expectException(CalcException::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AsinTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AsinTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerAsin
|
* @dataProvider providerAsin
|
||||||
|
|
@ -15,11 +11,8 @@ class AsinTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testAsin($expectedResult, string $formula): void
|
public function testAsin($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue(0.5);
|
$sheet->getCell('A2')->setValue(0.5);
|
||||||
$sheet->getCell('A1')->setValue("=ASIN($formula)");
|
$sheet->getCell('A1')->setValue("=ASIN($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AsinhTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AsinhTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerAsinh
|
* @dataProvider providerAsinh
|
||||||
|
|
@ -15,11 +11,8 @@ class AsinhTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testAsinh($expectedResult, string $formula): void
|
public function testAsinh($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue(0.5);
|
$sheet->getCell('A2')->setValue(0.5);
|
||||||
$sheet->getCell('A1')->setValue("=ASINH($formula)");
|
$sheet->getCell('A1')->setValue("=ASINH($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class Atan2Test extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class Atan2Test extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerATAN2
|
* @dataProvider providerATAN2
|
||||||
|
|
@ -15,11 +11,8 @@ class Atan2Test extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testATAN2($expectedResult, string $formula): void
|
public function testATAN2($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue(5);
|
$sheet->getCell('A2')->setValue(5);
|
||||||
$sheet->getCell('A3')->setValue(6);
|
$sheet->getCell('A3')->setValue(6);
|
||||||
$sheet->getCell('A1')->setValue("=ATAN2($formula)");
|
$sheet->getCell('A1')->setValue("=ATAN2($formula)");
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AtanTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AtanTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerAtan
|
* @dataProvider providerAtan
|
||||||
|
|
@ -15,11 +11,8 @@ class AtanTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testAtan($expectedResult, string $formula): void
|
public function testAtan($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue(5);
|
$sheet->getCell('A2')->setValue(5);
|
||||||
$sheet->getCell('A1')->setValue("=ATAN($formula)");
|
$sheet->getCell('A1')->setValue("=ATAN($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class AtanhTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AtanhTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerAtanh
|
* @dataProvider providerAtanh
|
||||||
|
|
@ -15,11 +11,8 @@ class AtanhTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testAtanh($expectedResult, string $formula): void
|
public function testAtanh($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A2')->setValue(0.8);
|
$sheet->getCell('A2')->setValue(0.8);
|
||||||
$sheet->getCell('A1')->setValue("=ATANH($formula)");
|
$sheet->getCell('A1')->setValue("=ATANH($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,39 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class BaseTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class BaseTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerBASE
|
* @dataProvider providerBASE
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $arg1
|
||||||
|
* @param mixed $arg2
|
||||||
|
* @param mixed $arg3
|
||||||
*/
|
*/
|
||||||
public function testBASE($expectedResult, ...$args): void
|
public function testBASE($expectedResult, $arg1 = 'omitted', $arg2 = 'omitted', $arg3 = 'omitted'): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::BASE(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if ($arg1 !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($arg1);
|
||||||
|
}
|
||||||
|
if ($arg2 !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($arg2);
|
||||||
|
}
|
||||||
|
if ($arg3 !== null) {
|
||||||
|
$sheet->getCell('A3')->setValue($arg3);
|
||||||
|
}
|
||||||
|
if ($arg1 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=BASE()');
|
||||||
|
} elseif ($arg2 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=BASE(A1)');
|
||||||
|
} elseif ($arg3 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=BASE(A1, A2)');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=BASE(A1, A2, A3)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEquals($expectedResult, $result);
|
self::assertEquals($expectedResult, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CeilingMathTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CeilingMathTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCEILINGMATH
|
* @dataProvider providerCEILINGMATH
|
||||||
|
|
@ -16,11 +12,8 @@ class CeilingMathTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCEILINGMATH($expectedResult, $formula): void
|
public function testCEILINGMATH($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CeilingPreciseTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CeilingPreciseTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerFLOORPRECISE
|
* @dataProvider providerFLOORPRECISE
|
||||||
|
|
@ -16,11 +12,8 @@ class CeilingPreciseTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCEILINGPRECISE($expectedResult, $formula): void
|
public function testCEILINGPRECISE($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CeilingTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CeilingTest extends TestCase
|
|
||||||
{
|
{
|
||||||
private $compatibilityMode;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
$this->compatibilityMode = Functions::getCompatibilityMode();
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode($this->compatibilityMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCEILING
|
* @dataProvider providerCEILING
|
||||||
*
|
*
|
||||||
|
|
@ -30,11 +12,8 @@ class CeilingTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCEILING($expectedResult, $formula): void
|
public function testCEILING($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
@ -51,9 +30,8 @@ class CeilingTest extends TestCase
|
||||||
|
|
||||||
public function testCEILINGGnumeric1Arg(): void
|
public function testCEILINGGnumeric1Arg(): void
|
||||||
{
|
{
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_GNUMERIC);
|
self::setGnumeric();
|
||||||
$spreadsheet = new Spreadsheet();
|
$sheet = $this->sheet;
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A1')->setValue('=CEILING(5.1)');
|
$sheet->getCell('A1')->setValue('=CEILING(5.1)');
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta(6, $result, 1E-12);
|
self::assertEqualsWithDelta(6, $result, 1E-12);
|
||||||
|
|
@ -61,20 +39,17 @@ class CeilingTest extends TestCase
|
||||||
|
|
||||||
public function testCELINGOpenOffice1Arg(): void
|
public function testCELINGOpenOffice1Arg(): void
|
||||||
{
|
{
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE);
|
self::setOpenOffice();
|
||||||
$spreadsheet = new Spreadsheet();
|
$sheet = $this->sheet;
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A1')->setValue('=CEILING(5.1)');
|
$sheet->getCell('A1')->setValue('=CEILING(5.1)');
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta(6, $result, 1E-12);
|
self::assertEqualsWithDelta(6, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFLOORExcel1Arg(): void
|
public function testCEILINGExcel1Arg(): void
|
||||||
{
|
{
|
||||||
$this->expectException(CalcExp::class);
|
$this->mightHaveException('exception');
|
||||||
$spreadsheet = new Spreadsheet();
|
$sheet = $this->sheet;
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
$sheet->getCell('A1')->setValue('=CEILING(5.1)');
|
$sheet->getCell('A1')->setValue('=CEILING(5.1)');
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta(6, $result, 1E-12);
|
self::assertEqualsWithDelta(6, $result, 1E-12);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CosTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CosTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCos
|
* @dataProvider providerCos
|
||||||
|
|
@ -15,11 +11,8 @@ class CosTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCos($expectedResult, string $formula): void
|
public function testCos($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 2);
|
$sheet->setCellValue('A2', 2);
|
||||||
$sheet->getCell('A1')->setValue("=COS($formula)");
|
$sheet->getCell('A1')->setValue("=COS($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CoshTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CoshTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCosh
|
* @dataProvider providerCosh
|
||||||
|
|
@ -15,11 +11,8 @@ class CoshTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCosh($expectedResult, string $formula): void
|
public function testCosh($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 2);
|
$sheet->setCellValue('A2', 2);
|
||||||
$sheet->getCell('A1')->setValue("=COSH($formula)");
|
$sheet->getCell('A1')->setValue("=COSH($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CotTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CotTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCOT
|
* @dataProvider providerCOT
|
||||||
|
|
@ -16,11 +12,8 @@ class CotTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCOT($expectedResult, $angle): void
|
public function testCOT($expectedResult, $angle): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CothTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CothTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCOTH
|
* @dataProvider providerCOTH
|
||||||
|
|
@ -16,11 +12,8 @@ class CothTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCOTH($expectedResult, $angle): void
|
public function testCOTH($expectedResult, $angle): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CscTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CscTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCSC
|
* @dataProvider providerCSC
|
||||||
|
|
@ -16,11 +12,8 @@ class CscTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCSC($expectedResult, $angle): void
|
public function testCSC($expectedResult, $angle): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class CschTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class CschTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCSCH
|
* @dataProvider providerCSCH
|
||||||
|
|
@ -16,11 +12,8 @@ class CschTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testCSCH($expectedResult, $angle): void
|
public function testCSCH($expectedResult, $angle): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class EvenTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class EvenTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerEVEN
|
* @dataProvider providerEVEN
|
||||||
|
|
@ -16,11 +12,8 @@ class EvenTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testEVEN($expectedResult, $value): void
|
public function testEVEN($expectedResult, $value): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A1')->setValue("=EVEN($value)");
|
$sheet->getCell('A1')->setValue("=EVEN($value)");
|
||||||
$sheet->getCell('A2')->setValue(3.7);
|
$sheet->getCell('A2')->setValue(3.7);
|
||||||
self::assertEquals($expectedResult, $sheet->getCell('A1')->getCalculatedValue());
|
self::assertEquals($expectedResult, $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
|
|
||||||
|
|
@ -2,31 +2,60 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class FactTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class FactTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerFACT
|
* @dataProvider providerFACT
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
* @param $value
|
* @param mixed $arg1
|
||||||
*/
|
*/
|
||||||
public function testFACT($expectedResult, $value): void
|
public function testFACT($expectedResult, $arg1): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::FACT($value);
|
$this->mightHaveException($expectedResult);
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
$sheet = $this->sheet;
|
||||||
|
if ($arg1 !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($arg1);
|
||||||
|
}
|
||||||
|
if ($arg1 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=FACT()');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=FACT(A1)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEquals($expectedResult, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerFACT()
|
public function providerFACT()
|
||||||
{
|
{
|
||||||
return require 'tests/data/Calculation/MathTrig/FACT.php';
|
return require 'tests/data/Calculation/MathTrig/FACT.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerFACTGnumeric
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $arg1
|
||||||
|
*/
|
||||||
|
public function testFACTGnumeric($expectedResult, $arg1): void
|
||||||
|
{
|
||||||
|
$this->mightHaveException($expectedResult);
|
||||||
|
self::setGnumeric();
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if ($arg1 !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($arg1);
|
||||||
|
}
|
||||||
|
if ($arg1 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=FACT()');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=FACT(A1)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEquals($expectedResult, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerFACTGnumeric()
|
||||||
|
{
|
||||||
|
return require 'tests/data/Calculation/MathTrig/FACTGNUMERIC.php';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class FloorMathTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class FloorMathTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerFLOORMATH
|
* @dataProvider providerFLOORMATH
|
||||||
|
|
@ -16,11 +12,8 @@ class FloorMathTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testFLOORMATH($expectedResult, $formula): void
|
public function testFLOORMATH($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class FloorPreciseTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class FloorPreciseTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerFLOORPRECISE
|
* @dataProvider providerFLOORPRECISE
|
||||||
|
|
@ -16,11 +12,8 @@ class FloorPreciseTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testFLOORPRECISE($expectedResult, $formula): void
|
public function testFLOORPRECISE($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class FloorTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class FloorTest extends TestCase
|
|
||||||
{
|
{
|
||||||
private $compatibilityMode;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
$this->compatibilityMode = Functions::getCompatibilityMode();
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode($this->compatibilityMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerFLOOR
|
* @dataProvider providerFLOOR
|
||||||
*
|
*
|
||||||
|
|
@ -30,11 +12,8 @@ class FloorTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testFLOOR($expectedResult, $formula): void
|
public function testFLOOR($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
@ -51,9 +30,8 @@ class FloorTest extends TestCase
|
||||||
|
|
||||||
public function testFLOORGnumeric1Arg(): void
|
public function testFLOORGnumeric1Arg(): void
|
||||||
{
|
{
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_GNUMERIC);
|
self::setGnumeric();
|
||||||
$spreadsheet = new Spreadsheet();
|
$sheet = $this->sheet;
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A1')->setValue('=FLOOR(5.1)');
|
$sheet->getCell('A1')->setValue('=FLOOR(5.1)');
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta(5, $result, 1E-12);
|
self::assertEqualsWithDelta(5, $result, 1E-12);
|
||||||
|
|
@ -61,9 +39,8 @@ class FloorTest extends TestCase
|
||||||
|
|
||||||
public function testFLOOROpenOffice1Arg(): void
|
public function testFLOOROpenOffice1Arg(): void
|
||||||
{
|
{
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE);
|
self::setOpenOffice();
|
||||||
$spreadsheet = new Spreadsheet();
|
$sheet = $this->sheet;
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A1')->setValue('=FLOOR(5.1)');
|
$sheet->getCell('A1')->setValue('=FLOOR(5.1)');
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta(5, $result, 1E-12);
|
self::assertEqualsWithDelta(5, $result, 1E-12);
|
||||||
|
|
@ -71,10 +48,8 @@ class FloorTest extends TestCase
|
||||||
|
|
||||||
public function testFLOORExcel1Arg(): void
|
public function testFLOORExcel1Arg(): void
|
||||||
{
|
{
|
||||||
$this->expectException(CalcExp::class);
|
$this->mightHaveException('exception');
|
||||||
$spreadsheet = new Spreadsheet();
|
$sheet = $this->sheet;
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
$sheet->getCell('A1')->setValue('=FLOOR(5.1)');
|
$sheet->getCell('A1')->setValue('=FLOOR(5.1)');
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta(5, $result, 1E-12);
|
self::assertEqualsWithDelta(5, $result, 1E-12);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class IntTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class IntTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerINT
|
* @dataProvider providerINT
|
||||||
|
|
@ -16,11 +12,8 @@ class IntTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testINT($expectedResult, $formula): void
|
public function testINT($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class LcmTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class LcmTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerLCM
|
* @dataProvider providerLCM
|
||||||
*
|
*
|
||||||
|
|
@ -20,7 +11,14 @@ class LcmTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testLCM($expectedResult, ...$args): void
|
public function testLCM($expectedResult, ...$args): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::LCM(...$args);
|
$sheet = $this->sheet;
|
||||||
|
$row = 0;
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
++$row;
|
||||||
|
$sheet->getCell("A$row")->setValue($arg);
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue("=LCM(A1:A$row)");
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,10 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class MInverseTest extends TestCase
|
class MInverseTest extends AllSetupTeardown
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerMINVERSE
|
* @dataProvider providerMINVERSE
|
||||||
*
|
*
|
||||||
|
|
@ -28,4 +21,12 @@ class MInverseTest extends TestCase
|
||||||
{
|
{
|
||||||
return require 'tests/data/Calculation/MathTrig/MINVERSE.php';
|
return require 'tests/data/Calculation/MathTrig/MINVERSE.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testOnSpreadsheet(): void
|
||||||
|
{
|
||||||
|
// very limited ability to test this in the absence of dynamic arrays
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$sheet->getCell('A1')->setValue('=MINVERSE({1,2,3})'); // not square
|
||||||
|
self::assertSame('#VALUE!', $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,10 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class MMultTest extends TestCase
|
class MMultTest extends AllSetupTeardown
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerMMULT
|
* @dataProvider providerMMULT
|
||||||
*
|
*
|
||||||
|
|
@ -28,4 +21,12 @@ class MMultTest extends TestCase
|
||||||
{
|
{
|
||||||
return require 'tests/data/Calculation/MathTrig/MMULT.php';
|
return require 'tests/data/Calculation/MathTrig/MMULT.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testOnSpreadsheet(): void
|
||||||
|
{
|
||||||
|
// very limited ability to test this in the absence of dynamic arrays
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$sheet->getCell('A1')->setValue('=MMULT({1,2,3}, {1,2,3})'); // incompatible dimensions
|
||||||
|
self::assertSame('#VALUE!', $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class MRoundTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class MRoundTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerMROUND
|
* @dataProvider providerMROUND
|
||||||
|
|
@ -16,11 +12,8 @@ class MRoundTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testMROUND($expectedResult, $formula): void
|
public function testMROUND($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,27 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class MdeTermTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class MdeTermTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerMDETERM
|
* @dataProvider providerMDETERM
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $matrix expect a matrix
|
||||||
*/
|
*/
|
||||||
public function testMDETERM($expectedResult, ...$args): void
|
public function testMDETERM2($expectedResult, $matrix): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::MDETERM(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
if (is_array($matrix)) {
|
||||||
|
$sheet->fromArray($matrix, null, 'A1', true);
|
||||||
|
$maxCol = $sheet->getHighestColumn();
|
||||||
|
$maxRow = $sheet->getHighestRow();
|
||||||
|
$sheet->getCell('Z1')->setValue("=MDETERM(A1:$maxCol$maxRow)");
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('Z1')->setValue("=MDETERM($matrix)");
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('Z1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class MovedFunctionsTest extends TestCase
|
||||||
self::assertEqualsWithDelta(0, MathTrig::builtinATAN(0), 1E-9);
|
self::assertEqualsWithDelta(0, MathTrig::builtinATAN(0), 1E-9);
|
||||||
self::assertEqualsWithDelta(0, MathTrig::builtinATANH(0), 1E-9);
|
self::assertEqualsWithDelta(0, MathTrig::builtinATANH(0), 1E-9);
|
||||||
self::assertEqualsWithDelta('#DIV/0!', MathTrig::ATAN2(0, 0), 1E-9);
|
self::assertEqualsWithDelta('#DIV/0!', MathTrig::ATAN2(0, 0), 1E-9);
|
||||||
|
self::assertEquals('12', MathTrig::BASE(10, 8));
|
||||||
self::assertEquals(-6, MathTrig::CEILING(-4.5, -2));
|
self::assertEquals(-6, MathTrig::CEILING(-4.5, -2));
|
||||||
self::assertEquals(1, MathTrig::builtinCOS(0));
|
self::assertEquals(1, MathTrig::builtinCOS(0));
|
||||||
self::assertEquals(1, MathTrig::builtinCOSH(0));
|
self::assertEquals(1, MathTrig::builtinCOSH(0));
|
||||||
|
|
@ -33,20 +34,40 @@ class MovedFunctionsTest extends TestCase
|
||||||
self::assertEquals('#DIV/0!', MathTrig::CSC(0));
|
self::assertEquals('#DIV/0!', MathTrig::CSC(0));
|
||||||
self::assertEquals('#DIV/0!', MathTrig::CSCH(0));
|
self::assertEquals('#DIV/0!', MathTrig::CSCH(0));
|
||||||
self::assertEquals(6, MathTrig::EVEN(4.5));
|
self::assertEquals(6, MathTrig::EVEN(4.5));
|
||||||
|
self::assertEquals(6, MathTrig::FACT(3));
|
||||||
self::assertEquals(-6, MathTrig::FLOOR(-4.5, 2));
|
self::assertEquals(-6, MathTrig::FLOOR(-4.5, 2));
|
||||||
self::assertEquals(0.23, MathTrig::FLOORMATH(0.234, 0.01));
|
self::assertEquals(0.23, MathTrig::FLOORMATH(0.234, 0.01));
|
||||||
self::assertEquals(-4, MathTrig::FLOORPRECISE(-2.5, 2));
|
self::assertEquals(-4, MathTrig::FLOORPRECISE(-2.5, 2));
|
||||||
self::assertEquals(-9, MathTrig::INT(-8.3));
|
self::assertEquals(-9, MathTrig::INT(-8.3));
|
||||||
|
self::assertEquals(12, MathTrig::LCM(4, 6));
|
||||||
|
self::assertEquals(1, MathTrig::MDETERM([1]));
|
||||||
|
self::assertEquals(
|
||||||
|
[[2, 2], [2, 1]],
|
||||||
|
MathTrig::MINVERSE([[-0.5, 1.0], [1.0, -1.0]])
|
||||||
|
);
|
||||||
|
self::assertEquals(
|
||||||
|
[[23], [53]],
|
||||||
|
MathTrig::MMULT([[1, 2], [3, 4]], [[7], [8]])
|
||||||
|
);
|
||||||
self::assertEquals(6, MathTrig::MROUND(7.3, 3));
|
self::assertEquals(6, MathTrig::MROUND(7.3, 3));
|
||||||
|
self::assertEquals(1, MathTrig::MULTINOMIAL(1));
|
||||||
self::assertEquals(5, MathTrig::ODD(4.5));
|
self::assertEquals(5, MathTrig::ODD(4.5));
|
||||||
|
self::assertEquals(8, MathTrig::PRODUCT(1, 2, 4));
|
||||||
|
self::assertEquals(8, MathTrig::QUOTIENT(17, 2));
|
||||||
|
self::assertEquals('I', MathTrig::ROMAN(1));
|
||||||
self::assertEquals(3.3, MathTrig::builtinROUND(3.27, 1));
|
self::assertEquals(3.3, MathTrig::builtinROUND(3.27, 1));
|
||||||
self::assertEquals(662, MathTrig::ROUNDDOWN(662.79, 0));
|
self::assertEquals(662, MathTrig::ROUNDDOWN(662.79, 0));
|
||||||
self::assertEquals(663, MathTrig::ROUNDUP(662.79, 0));
|
self::assertEquals(663, MathTrig::ROUNDUP(662.79, 0));
|
||||||
self::assertEquals(1, MathTrig::SEC(0));
|
self::assertEquals(1, MathTrig::SEC(0));
|
||||||
self::assertEquals(1, MathTrig::SECH(0));
|
self::assertEquals(1, MathTrig::SECH(0));
|
||||||
|
self::assertEquals(3780, MathTrig::SERIESSUM(5, 1, 1, [1, 1, 0, 1, 1]));
|
||||||
self::assertEquals(1, MathTrig::SIGN(79.2));
|
self::assertEquals(1, MathTrig::SIGN(79.2));
|
||||||
self::assertEquals(0, MathTrig::builtinSIN(0));
|
self::assertEquals(0, MathTrig::builtinSIN(0));
|
||||||
self::assertEquals(0, MathTrig::builtinSINH(0));
|
self::assertEquals(0, MathTrig::builtinSINH(0));
|
||||||
|
self::assertEquals(0, MathTrig::SUBTOTAL(2, [0, 0]));
|
||||||
|
self::assertEquals(7, MathTrig::SUM(1, 2, 4));
|
||||||
|
self::assertEquals(4, MathTrig::SUMIF([[2], [4]], '>2'));
|
||||||
|
self::assertEquals(17, MathTrig::SUMPRODUCT([1, 2, 3], [5, 0, 4]));
|
||||||
self::assertEquals(0, MathTrig::builtinTAN(0));
|
self::assertEquals(0, MathTrig::builtinTAN(0));
|
||||||
self::assertEquals(0, MathTrig::builtinTANH(0));
|
self::assertEquals(0, MathTrig::builtinTANH(0));
|
||||||
self::assertEquals(70, MathTrig::TRUNC(79.2, -1));
|
self::assertEquals(70, MathTrig::TRUNC(79.2, -1));
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class MultinomialTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class MultinomialTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerMULTINOMIAL
|
* @dataProvider providerMULTINOMIAL
|
||||||
*
|
*
|
||||||
|
|
@ -20,7 +11,19 @@ class MultinomialTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testMULTINOMIAL($expectedResult, ...$args): void
|
public function testMULTINOMIAL($expectedResult, ...$args): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::MULTINOMIAL(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$row = 0;
|
||||||
|
$excelArg = '';
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
++$row;
|
||||||
|
$excelArg = "A1:A$row";
|
||||||
|
if ($arg !== null) {
|
||||||
|
$sheet->getCell("A$row")->setValue($arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue("=MULTINOMIAL($excelArg)");
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class OddTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class OddTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerODD
|
* @dataProvider providerODD
|
||||||
|
|
@ -16,11 +12,8 @@ class OddTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testODD($expectedResult, $value): void
|
public function testODD($expectedResult, $value): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->getCell('A1')->setValue("=ODD($value)");
|
$sheet->getCell('A1')->setValue("=ODD($value)");
|
||||||
$sheet->getCell('A2')->setValue(3.7);
|
$sheet->getCell('A2')->setValue(3.7);
|
||||||
self::assertEquals($expectedResult, $sheet->getCell('A1')->getCalculatedValue());
|
self::assertEquals($expectedResult, $sheet->getCell('A1')->getCalculatedValue());
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class ProductTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class ProductTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerPRODUCT
|
* @dataProvider providerPRODUCT
|
||||||
*
|
*
|
||||||
|
|
@ -20,7 +11,14 @@ class ProductTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testPRODUCT($expectedResult, ...$args): void
|
public function testPRODUCT($expectedResult, ...$args): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::PRODUCT(...$args);
|
$sheet = $this->sheet;
|
||||||
|
$row = 0;
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
++$row;
|
||||||
|
$sheet->getCell("A$row")->setValue($arg);
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue("=PRODUCT(A1:A$row)");
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,34 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class QuotientTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class QuotientTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerQUOTIENT
|
* @dataProvider providerQUOTIENT
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $arg1
|
||||||
|
* @param mixed $arg2
|
||||||
*/
|
*/
|
||||||
public function testQUOTIENT($expectedResult, ...$args): void
|
public function testQUOTIENT($expectedResult, $arg1 = 'omitted', $arg2 = 'omitted'): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::QUOTIENT(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
$sheet = $this->sheet;
|
||||||
|
if ($arg1 !== null) {
|
||||||
|
$sheet->getCell('A1')->setValue($arg1);
|
||||||
|
}
|
||||||
|
if ($arg2 !== null) {
|
||||||
|
$sheet->getCell('A2')->setValue($arg2);
|
||||||
|
}
|
||||||
|
if ($arg1 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=QUOTIENT()');
|
||||||
|
} elseif ($arg2 === 'omitted') {
|
||||||
|
$sheet->getCell('B1')->setValue('=QUOTIENT(A1)');
|
||||||
|
} else {
|
||||||
|
$sheet->getCell('B1')->setValue('=QUOTIENT(A1, A2)');
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertSame($expectedResult, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerQUOTIENT()
|
public function providerQUOTIENT()
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class RomanTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class RomanTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerROMAN
|
* @dataProvider providerROMAN
|
||||||
|
|
@ -16,11 +12,8 @@ class RomanTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testROMAN($expectedResult, $formula): void
|
public function testROMAN($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A3', 49);
|
$sheet->setCellValue('A3', 49);
|
||||||
$sheet->getCell('A1')->setValue("=ROMAN($formula)");
|
$sheet->getCell('A1')->setValue("=ROMAN($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
@ -31,11 +24,4 @@ class RomanTest extends TestCase
|
||||||
{
|
{
|
||||||
return require 'tests/data/Calculation/MathTrig/ROMAN.php';
|
return require 'tests/data/Calculation/MathTrig/ROMAN.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm that deprecated stub left in MathTrig works.
|
|
||||||
// Delete this test when stub is finally deleted.
|
|
||||||
public function testDeprecated(): void
|
|
||||||
{
|
|
||||||
self::assertEquals('I', \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROMAN(1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class RoundDownTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class RoundDownTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerRoundDown
|
* @dataProvider providerRoundDown
|
||||||
|
|
@ -16,11 +12,8 @@ class RoundDownTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testRoundDown($expectedResult, $formula): void
|
public function testRoundDown($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class RoundTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class RoundTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerRound
|
* @dataProvider providerRound
|
||||||
|
|
@ -16,11 +12,8 @@ class RoundTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testRound($expectedResult, $formula): void
|
public function testRound($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class RoundUpTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class RoundUpTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerRoundUp
|
* @dataProvider providerRoundUp
|
||||||
|
|
@ -16,11 +12,8 @@ class RoundUpTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testRoundUp($expectedResult, $formula): void
|
public function testRoundUp($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class SecTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SecTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSEC
|
* @dataProvider providerSEC
|
||||||
|
|
@ -16,11 +12,8 @@ class SecTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testSEC($expectedResult, $angle): void
|
public function testSEC($expectedResult, $angle): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class SechTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SechTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSECH
|
* @dataProvider providerSECH
|
||||||
|
|
@ -16,11 +12,8 @@ class SechTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testSECH($expectedResult, $angle): void
|
public function testSECH($expectedResult, $angle): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,39 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SeriesSumTest extends TestCase
|
class SeriesSumTest extends AllSetupTeardown
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSERIESSUM
|
* @dataProvider providerSERIESSUM
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $arg1
|
||||||
|
* @param mixed $arg2
|
||||||
|
* @param mixed $arg3
|
||||||
*/
|
*/
|
||||||
public function testSERIESSUM($expectedResult, ...$args): void
|
public function testSERIESSUM($expectedResult, $arg1, $arg2, $arg3, ...$args): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::SERIESSUM(...$args);
|
$sheet = $this->sheet;
|
||||||
|
if ($arg1 !== null) {
|
||||||
|
$sheet->getCell('C1')->setValue($arg1);
|
||||||
|
}
|
||||||
|
if ($arg2 !== null) {
|
||||||
|
$sheet->getCell('C2')->setValue($arg2);
|
||||||
|
}
|
||||||
|
if ($arg3 !== null) {
|
||||||
|
$sheet->getCell('C3')->setValue($arg3);
|
||||||
|
}
|
||||||
|
$row = 0;
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
foreach ($aArgs as $arg) {
|
||||||
|
++$row;
|
||||||
|
if ($arg !== null) {
|
||||||
|
$sheet->getCell("A$row")->setValue($arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue("=SERIESSUM(C1, C2, C3, A1:A$row)");
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class SignTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SignTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSIGN
|
* @dataProvider providerSIGN
|
||||||
|
|
@ -16,11 +12,8 @@ class SignTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testSIGN($expectedResult, $value): void
|
public function testSIGN($expectedResult, $value): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 0);
|
$sheet->setCellValue('A3', 0);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class SinTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SinTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSin
|
* @dataProvider providerSin
|
||||||
|
|
@ -15,11 +11,8 @@ class SinTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testSin($expectedResult, string $formula): void
|
public function testSin($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 2);
|
$sheet->setCellValue('A2', 2);
|
||||||
$sheet->getCell('A1')->setValue("=SIN($formula)");
|
$sheet->getCell('A1')->setValue("=SIN($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class SinhTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SinhTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerCosh
|
* @dataProvider providerCosh
|
||||||
|
|
@ -15,11 +11,8 @@ class SinhTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testSinh($expectedResult, string $formula): void
|
public function testSinh($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 2);
|
$sheet->setCellValue('A2', 2);
|
||||||
$sheet->getCell('A1')->setValue("=SINH($formula)");
|
$sheet->getCell('A1')->setValue("=SINH($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,53 +2,23 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class SubTotalTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\ColumnDimension;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SubTotalTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSUBTOTAL
|
* @dataProvider providerSUBTOTAL
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $type expect an integer
|
||||||
*/
|
*/
|
||||||
public function testSUBTOTAL($expectedResult, ...$args): void
|
public function testSubtotal($expectedResult, $type): void
|
||||||
{
|
{
|
||||||
$cell = $this->getMockBuilder(Cell::class)
|
$this->mightHaveException($expectedResult);
|
||||||
->onlyMethods(['getValue', 'isFormula'])
|
$sheet = $this->sheet;
|
||||||
->disableOriginalConstructor()
|
$sheet->fromArray([[0], [1], [1], [2], [3], [5], [8], [13], [21], [34], [55], [89]], null, 'A1', true);
|
||||||
->getMock();
|
$maxCol = $sheet->getHighestColumn();
|
||||||
$cell->method('getValue')
|
$maxRow = $sheet->getHighestRow();
|
||||||
->willReturn(null);
|
$sheet->getCell('D2')->setValue("=SUBTOTAL($type, A1:$maxCol$maxRow)");
|
||||||
$cell->method('getValue')
|
$result = $sheet->getCell('D2')->getCalculatedValue();
|
||||||
->willReturn(false);
|
|
||||||
$worksheet = $this->getMockBuilder(Worksheet::class)
|
|
||||||
->onlyMethods(['cellExists', 'getCell'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$worksheet->method('cellExists')
|
|
||||||
->willReturn(true);
|
|
||||||
$worksheet->method('getCell')
|
|
||||||
->willReturn($cell);
|
|
||||||
$cellReference = $this->getMockBuilder(Cell::class)
|
|
||||||
->onlyMethods(['getWorksheet'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$cellReference->method('getWorksheet')
|
|
||||||
->willReturn($worksheet);
|
|
||||||
|
|
||||||
array_push($args, $cellReference);
|
|
||||||
$result = MathTrig::SUBTOTAL(...$args);
|
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,142 +27,102 @@ class SubTotalTest extends TestCase
|
||||||
return require 'tests/data/Calculation/MathTrig/SUBTOTAL.php';
|
return require 'tests/data/Calculation/MathTrig/SUBTOTAL.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function rowVisibility($data)
|
|
||||||
{
|
|
||||||
foreach ($data as $row => $visibility) {
|
|
||||||
yield $row => $visibility;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerHiddenSUBTOTAL
|
* @dataProvider providerSUBTOTAL
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
* @param mixed $hiddenRows
|
* @param mixed $type expect an integer
|
||||||
*/
|
*/
|
||||||
public function testHiddenSUBTOTAL($expectedResult, $hiddenRows, ...$args): void
|
public function testSubtotalColumnHidden($expectedResult, $type): void
|
||||||
{
|
{
|
||||||
$visibilityGenerator = $this->rowVisibility($hiddenRows);
|
// Hidden columns don't affect calculation, only hidden rows
|
||||||
|
$this->mightHaveException($expectedResult);
|
||||||
$rowDimension = $this->getMockBuilder(RowDimension::class)
|
$sheet = $this->sheet;
|
||||||
->onlyMethods(['getVisible'])
|
$sheet->fromArray([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89], null, 'A1', true);
|
||||||
->disableOriginalConstructor()
|
$maxCol = $sheet->getHighestColumn();
|
||||||
->getMock();
|
$maxRow = $sheet->getHighestRow();
|
||||||
$rowDimension->method('getVisible')
|
$hiddenColumns = [
|
||||||
->willReturnCallback(function () use ($visibilityGenerator) {
|
'A' => false,
|
||||||
$result = $visibilityGenerator->current();
|
'B' => true,
|
||||||
$visibilityGenerator->next();
|
'C' => false,
|
||||||
|
'D' => true,
|
||||||
return $result;
|
'E' => false,
|
||||||
});
|
'F' => false,
|
||||||
$columnDimension = $this->getMockBuilder(ColumnDimension::class)
|
'G' => false,
|
||||||
->onlyMethods(['getVisible'])
|
'H' => true,
|
||||||
->disableOriginalConstructor()
|
'I' => false,
|
||||||
->getMock();
|
'J' => true,
|
||||||
$columnDimension->method('getVisible')
|
'K' => true,
|
||||||
->willReturn(true);
|
'L' => false,
|
||||||
$cell = $this->getMockBuilder(Cell::class)
|
];
|
||||||
->onlyMethods(['getValue', 'isFormula'])
|
foreach ($hiddenColumns as $col => $hidden) {
|
||||||
->disableOriginalConstructor()
|
$sheet->getColumnDimension($col)->setVisible($hidden);
|
||||||
->getMock();
|
}
|
||||||
$cell->method('getValue')
|
$sheet->getCell('D2')->setValue("=SUBTOTAL($type, A1:$maxCol$maxRow)");
|
||||||
->willReturn('');
|
$result = $sheet->getCell('D2')->getCalculatedValue();
|
||||||
$cell->method('getValue')
|
|
||||||
->willReturn(false);
|
|
||||||
$worksheet = $this->getMockBuilder(Worksheet::class)
|
|
||||||
->onlyMethods(['cellExists', 'getCell', 'getRowDimension', 'getColumnDimension'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$worksheet->method('cellExists')
|
|
||||||
->willReturn(true);
|
|
||||||
$worksheet->method('getCell')
|
|
||||||
->willReturn($cell);
|
|
||||||
$worksheet->method('getRowDimension')
|
|
||||||
->willReturn($rowDimension);
|
|
||||||
$worksheet->method('getColumnDimension')
|
|
||||||
->willReturn($columnDimension);
|
|
||||||
$cellReference = $this->getMockBuilder(Cell::class)
|
|
||||||
->onlyMethods(['getWorksheet'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$cellReference->method('getWorksheet')
|
|
||||||
->willReturn($worksheet);
|
|
||||||
|
|
||||||
array_push($args, $cellReference);
|
|
||||||
$result = MathTrig::SUBTOTAL(...$args);
|
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerHiddenSUBTOTAL()
|
/**
|
||||||
|
* @dataProvider providerSUBTOTALHIDDEN
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $type expect an integer
|
||||||
|
*/
|
||||||
|
public function testSubtotalRowHidden($expectedResult, $type): void
|
||||||
|
{
|
||||||
|
$this->mightHaveException($expectedResult);
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$sheet->fromArray([[0], [1], [1], [2], [3], [5], [8], [13], [21], [34], [55], [89]], null, 'A1', true);
|
||||||
|
$maxCol = $sheet->getHighestColumn();
|
||||||
|
$maxRow = $sheet->getHighestRow();
|
||||||
|
$visibleRows = [
|
||||||
|
'1' => false,
|
||||||
|
'2' => true,
|
||||||
|
'3' => false,
|
||||||
|
'4' => true,
|
||||||
|
'5' => false,
|
||||||
|
'6' => false,
|
||||||
|
'7' => false,
|
||||||
|
'8' => true,
|
||||||
|
'9' => false,
|
||||||
|
'10' => true,
|
||||||
|
'11' => true,
|
||||||
|
'12' => false,
|
||||||
|
];
|
||||||
|
foreach ($visibleRows as $row => $visible) {
|
||||||
|
$sheet->getRowDimension($row)->setVisible($visible);
|
||||||
|
}
|
||||||
|
$sheet->getCell('D2')->setValue("=SUBTOTAL($type, A1:$maxCol$maxRow)");
|
||||||
|
$result = $sheet->getCell('D2')->getCalculatedValue();
|
||||||
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerSUBTOTALHIDDEN()
|
||||||
{
|
{
|
||||||
return require 'tests/data/Calculation/MathTrig/SUBTOTALHIDDEN.php';
|
return require 'tests/data/Calculation/MathTrig/SUBTOTALHIDDEN.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function cellValues(array $cellValues)
|
public function testSubtotalNested(): void
|
||||||
{
|
{
|
||||||
foreach ($cellValues as $k => $v) {
|
$sheet = $this->sheet;
|
||||||
yield $k => $v;
|
$sheet->fromArray(
|
||||||
}
|
[
|
||||||
}
|
[123],
|
||||||
|
[234],
|
||||||
protected function cellIsFormula(array $cellValues)
|
['=SUBTOTAL(1,A1:A2)'],
|
||||||
{
|
['=ROMAN(SUBTOTAL(1, A1:A2))'],
|
||||||
foreach ($cellValues as $cellValue) {
|
['This is text containing "=" and "SUBTOTAL("'],
|
||||||
yield is_string($cellValue) && $cellValue[0] === '=';
|
['=AGGREGATE(1, 0, A1:A2)'],
|
||||||
}
|
['=SUM(2, 3)'],
|
||||||
}
|
],
|
||||||
|
null,
|
||||||
/**
|
'A1',
|
||||||
* @dataProvider providerNestedSUBTOTAL
|
true
|
||||||
*
|
);
|
||||||
* @param mixed $expectedResult
|
$maxCol = $sheet->getHighestColumn();
|
||||||
*/
|
$maxRow = $sheet->getHighestRow();
|
||||||
public function testNestedSUBTOTAL($expectedResult, ...$args): void
|
$sheet->getCell('H1')->setValue("=SUBTOTAL(9, A1:$maxCol$maxRow)");
|
||||||
{
|
self::assertEquals(362, $sheet->getCell('H1')->getCalculatedValue());
|
||||||
$cellValueGenerator = $this->cellValues(Functions::flattenArray(array_slice($args, 1)));
|
|
||||||
$cellIsFormulaGenerator = $this->cellIsFormula(Functions::flattenArray(array_slice($args, 1)));
|
|
||||||
|
|
||||||
$cell = $this->getMockBuilder(Cell::class)
|
|
||||||
->onlyMethods(['getValue', 'isFormula'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$cell->method('getValue')
|
|
||||||
->willReturnCallback(function () use ($cellValueGenerator) {
|
|
||||||
$result = $cellValueGenerator->current();
|
|
||||||
$cellValueGenerator->next();
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
});
|
|
||||||
$cell->method('isFormula')
|
|
||||||
->willReturnCallback(function () use ($cellIsFormulaGenerator) {
|
|
||||||
$result = $cellIsFormulaGenerator->current();
|
|
||||||
$cellIsFormulaGenerator->next();
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
});
|
|
||||||
$worksheet = $this->getMockBuilder(Worksheet::class)
|
|
||||||
->onlyMethods(['cellExists', 'getCell'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$worksheet->method('cellExists')
|
|
||||||
->willReturn(true);
|
|
||||||
$worksheet->method('getCell')
|
|
||||||
->willReturn($cell);
|
|
||||||
$cellReference = $this->getMockBuilder(Cell::class)
|
|
||||||
->onlyMethods(['getWorksheet'])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$cellReference->method('getWorksheet')
|
|
||||||
->willReturn($worksheet);
|
|
||||||
|
|
||||||
array_push($args, $cellReference);
|
|
||||||
|
|
||||||
$result = MathTrig::SUBTOTAL(...$args);
|
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function providerNestedSUBTOTAL()
|
|
||||||
{
|
|
||||||
return require 'tests/data/Calculation/MathTrig/SUBTOTALNESTED.php';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,36 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
class SumIfTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SumIfTest extends TestCase
|
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSUMIF
|
* @dataProvider providerSUMIF
|
||||||
*
|
*
|
||||||
* @param mixed $expectedResult
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $condition
|
||||||
*/
|
*/
|
||||||
public function testSUMIF($expectedResult, ...$args): void
|
public function testSUMIF2($expectedResult, array $array1, $condition, ?array $array2 = null): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::SUMIF(...$args);
|
$this->mightHaveException($expectedResult);
|
||||||
|
if ($expectedResult === 'incomplete') {
|
||||||
|
self::markTestIncomplete('Raises formula error - researching solution');
|
||||||
|
}
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$sheet->fromArray($array1, null, 'A1', true);
|
||||||
|
$maxARow = count($array1);
|
||||||
|
$firstArg = "A1:A$maxARow";
|
||||||
|
//$secondArg = is_string($condition) ? "\"$condition\"" : $condition;
|
||||||
|
$sheet->getCell('B1')->setValue($condition);
|
||||||
|
$secondArg = 'B1';
|
||||||
|
if (empty($array2)) {
|
||||||
|
$sheet->getCell('D1')->setValue("=SUMIF($firstArg, $secondArg)");
|
||||||
|
} else {
|
||||||
|
$sheet->fromArray($array2, null, 'C1', true);
|
||||||
|
$maxCRow = count($array2);
|
||||||
|
$thirdArg = "C1:C$maxCRow";
|
||||||
|
$sheet->getCell('D1')->setValue("=SUMIF($firstArg, $secondArg, $thirdArg)");
|
||||||
|
}
|
||||||
|
$result = $sheet->getCell('D1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,9 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class SumProductTest extends TestCase
|
class SumProductTest extends AllSetupTeardown
|
||||||
{
|
{
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerSUMPRODUCT
|
* @dataProvider providerSUMPRODUCT
|
||||||
*
|
*
|
||||||
|
|
@ -20,7 +13,24 @@ class SumProductTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testSUMPRODUCT($expectedResult, ...$args): void
|
public function testSUMPRODUCT($expectedResult, ...$args): void
|
||||||
{
|
{
|
||||||
$result = MathTrig::SUMPRODUCT(...$args);
|
$sheet = $this->sheet;
|
||||||
|
$row = 0;
|
||||||
|
$arrayArg = '';
|
||||||
|
foreach ($args as $arr) {
|
||||||
|
$arr2 = Functions::flattenArray($arr);
|
||||||
|
$startRow = 0;
|
||||||
|
foreach ($arr2 as $arr3) {
|
||||||
|
++$row;
|
||||||
|
if (!$startRow) {
|
||||||
|
$startRow = $row;
|
||||||
|
}
|
||||||
|
$sheet->getCell("A$row")->setValue($arr3);
|
||||||
|
}
|
||||||
|
$arrayArg .= "A$startRow:A$row,";
|
||||||
|
}
|
||||||
|
$arrayArg = substr($arrayArg, 0, -1); // strip trailing comma
|
||||||
|
$sheet->getCell('B1')->setValue("=SUMPRODUCT($arrayArg)");
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
|
class SumTest extends AllSetupTeardown
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider providerSUM
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
*/
|
||||||
|
public function testSUM($expectedResult, ...$args): void
|
||||||
|
{
|
||||||
|
$sheet = $this->sheet;
|
||||||
|
$row = 0;
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
++$row;
|
||||||
|
$sheet->getCell("A$row")->setValue($arg);
|
||||||
|
}
|
||||||
|
$sheet->getCell('B1')->setValue("=SUM(A1:A$row)");
|
||||||
|
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||||
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerSUM()
|
||||||
|
{
|
||||||
|
return require 'tests/data/Calculation/MathTrig/SUM.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class TanTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class TanTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerTan
|
* @dataProvider providerTan
|
||||||
|
|
@ -15,11 +11,8 @@ class TanTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testTan($expectedResult, string $formula): void
|
public function testTan($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1);
|
$sheet->setCellValue('A2', 1);
|
||||||
$sheet->getCell('A1')->setValue("=TAN($formula)");
|
$sheet->getCell('A1')->setValue("=TAN($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class TanhTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class TanhTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerTanh
|
* @dataProvider providerTanh
|
||||||
|
|
@ -15,11 +11,8 @@ class TanhTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testTanh($expectedResult, string $formula): void
|
public function testTanh($expectedResult, string $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1);
|
$sheet->setCellValue('A2', 1);
|
||||||
$sheet->getCell('A1')->setValue("=TANH($formula)");
|
$sheet->getCell('A1')->setValue("=TANH($formula)");
|
||||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
class TruncTest extends AllSetupTeardown
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class TruncTest extends TestCase
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerTRUNC
|
* @dataProvider providerTRUNC
|
||||||
|
|
@ -16,11 +12,8 @@ class TruncTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testTRUNC($expectedResult, $formula): void
|
public function testTRUNC($expectedResult, $formula): void
|
||||||
{
|
{
|
||||||
if ($expectedResult === 'exception') {
|
$this->mightHaveException($expectedResult);
|
||||||
$this->expectException(CalcExp::class);
|
$sheet = $this->sheet;
|
||||||
}
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A2', 1.3);
|
$sheet->setCellValue('A2', 1.3);
|
||||||
$sheet->setCellValue('A3', 2.7);
|
$sheet->setCellValue('A3', 2.7);
|
||||||
$sheet->setCellValue('A4', -3.8);
|
$sheet->setCellValue('A4', -3.8);
|
||||||
|
|
|
||||||
|
|
@ -56,4 +56,10 @@ return [
|
||||||
15,
|
15,
|
||||||
-1,
|
-1,
|
||||||
],
|
],
|
||||||
|
['#VALUE!', 15, -1, '"X"'],
|
||||||
|
['#NUM!', 15, 37], // radix > 36
|
||||||
|
['#NUM!', 2 ** 54, 16], // number > 2 ** 53
|
||||||
|
['00000120', 15, 3, 8.1],
|
||||||
|
['exception'],
|
||||||
|
['exception', 1],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
1,
|
1,
|
||||||
1.8999999999999999,
|
1.9,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
1,
|
1,
|
||||||
|
|
@ -35,7 +35,7 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
6,
|
6,
|
||||||
3.2000000000000002,
|
3.2,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#VALUE!',
|
'#VALUE!',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
120,
|
||||||
|
5,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1.82735508062404,
|
||||||
|
1.9,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
-4,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
720,
|
||||||
|
6,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3628800,
|
||||||
|
10,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
7.75668953579318,
|
||||||
|
3.2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!',
|
||||||
|
'ABC',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
@ -65,4 +65,9 @@ return [
|
||||||
7,
|
7,
|
||||||
2,
|
2,
|
||||||
],
|
],
|
||||||
|
['#NUM!', 7, 0, -1],
|
||||||
|
['#VALUE!', 7, 0, 'X'],
|
||||||
|
[18, 9.1, 6.7],
|
||||||
|
[12, 6, null, 4],
|
||||||
|
['#VALUE!', 6, false, 4],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,14 @@ return [
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#VALUE!',
|
-3,
|
||||||
|
[
|
||||||
|
[3, '=6'],
|
||||||
|
[1, 1],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // null in array
|
||||||
[
|
[
|
||||||
[0.20, 1.00, -0.90],
|
[0.20, 1.00, -0.90],
|
||||||
[0.35, 10.80, 4.00],
|
[0.35, 10.80, 4.00],
|
||||||
|
|
@ -103,10 +110,33 @@ return [
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#VALUE!',
|
'#VALUE!', // string in array
|
||||||
|
[
|
||||||
|
[0.20, 1.00, -0.90],
|
||||||
|
[0.35, 10.80, '="4.00"'],
|
||||||
|
[-3.15, 5.00, 6.00],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // string in array
|
||||||
|
[
|
||||||
|
[0.20, 1.00, -0.90],
|
||||||
|
[0.35, 10.80, 'Y'],
|
||||||
|
[-3.15, 5.00, 6.00],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // not square
|
||||||
[
|
[
|
||||||
[1, 3, 8, 5],
|
[1, 3, 8, 5],
|
||||||
[1, 3, 6, 1],
|
[1, 3, 6, 1],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[1, '{3,6,1;1,1,0;3,10,2}'], // bracket notation
|
||||||
|
[2, 2], // scalar treated as 1x1
|
||||||
|
['#VALUE!', '"y"'], // invalid scalar treated as 1x1
|
||||||
|
['#VALUE!', '"2"'], // invalid scalar treated as 1x1
|
||||||
|
['#VALUE!', '{3,6,1;1,1,0}'], // not square
|
||||||
|
['#VALUE!', '{3,6, "y";1,1,0;3,10,2}'], // first row has string entry
|
||||||
|
['exception', ''],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -111,4 +111,32 @@ return [
|
||||||
[1.0, -1.0],
|
[1.0, -1.0],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // Not Square
|
||||||
|
[
|
||||||
|
[-0.5, 1.0, 1.5],
|
||||||
|
[1.0, -1.0, 2.0],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!', // Determinant is 0
|
||||||
|
[
|
||||||
|
[3, 4],
|
||||||
|
[6, 8],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // null in array
|
||||||
|
[
|
||||||
|
[3, null],
|
||||||
|
[6, 8],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // string in array
|
||||||
|
[
|
||||||
|
[3, 4],
|
||||||
|
['6', 8],
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,28 @@ return [
|
||||||
[6],
|
[6],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // null in first array
|
||||||
|
[
|
||||||
|
[1, 2],
|
||||||
|
[null, 4],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[5],
|
||||||
|
[6],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#VALUE!', // string in second array
|
||||||
|
[
|
||||||
|
[1, 2],
|
||||||
|
[3, 4],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
['5'],
|
||||||
|
[6],
|
||||||
|
],
|
||||||
|
],
|
||||||
// Mismatched dimensions (2x2) and (1x1)
|
// Mismatched dimensions (2x2) and (1x1)
|
||||||
[
|
[
|
||||||
'#VALUE!',
|
'#VALUE!',
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,10 @@ return [
|
||||||
2,
|
2,
|
||||||
5,
|
5,
|
||||||
],
|
],
|
||||||
|
[1, 0],
|
||||||
|
['#NUM!', 3, -1],
|
||||||
|
['#VALUE!', 3, 'X'],
|
||||||
|
['#VALUE!', 3, null],
|
||||||
|
['#VALUE!', 3, true],
|
||||||
|
['exception'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -48,4 +48,6 @@ return [
|
||||||
-6.7800000000000002,
|
-6.7800000000000002,
|
||||||
-2,
|
-2,
|
||||||
],
|
],
|
||||||
|
['#VALUE!', 1, 'y', 3],
|
||||||
|
[6, 1, '2', 3],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,12 @@ return [
|
||||||
-7,
|
-7,
|
||||||
2,
|
2,
|
||||||
],
|
],
|
||||||
|
['#VALUE!', 'X', 5],
|
||||||
|
['#VALUE!', 5, 'X'],
|
||||||
|
['#DIV/0!', 5, 0],
|
||||||
|
['#DIV/0!', 5, null],
|
||||||
|
['#DIV/0!', 0, 0],
|
||||||
|
[0, 0, 5],
|
||||||
|
['exception'],
|
||||||
|
['exception', 1],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,16 @@ return [
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
['#VALUE!', 'X', 1, 2, [1, 2, 3, 4, 5]],
|
||||||
|
['#VALUE!', 2, 'X', 2, [1, 2, 3, 4, 5]],
|
||||||
|
['#VALUE!', 2, 1, 'X', [1, 2, 3, 4, 5]],
|
||||||
|
['#VALUE!', 2, 1, 2, [1, 'X', 3, 4, 5]],
|
||||||
|
['#VALUE!', true, 1, 2, [1, 'X', 3, 4, 5]],
|
||||||
|
['#VALUE!', 2, 1, 2, [1, false, 3, 4, 5]],
|
||||||
|
[780, 5, 1, 1, [1, 1, null, 1, 1]],
|
||||||
|
[3780, 5, 1, 1, [1, 1, 0, 1, 1]],
|
||||||
|
[756, 5, 0, 1, [1, 1, 0, 1, 1]],
|
||||||
|
[756, 5, null, 1, [1, 1, 0, 1, 1]],
|
||||||
|
[151.2, 5, -1, 1, [1, 1, 0, 1, 1]],
|
||||||
|
[138.7, 5, -1, 1, [1, 1, -2.5, 1, 1]],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,19 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$baseTestData = [
|
|
||||||
1 => ['A' => 0],
|
|
||||||
2 => ['A' => 1],
|
|
||||||
3 => ['A' => 1],
|
|
||||||
4 => ['A' => 2],
|
|
||||||
5 => ['A' => 3],
|
|
||||||
6 => ['A' => 5],
|
|
||||||
7 => ['A' => 8],
|
|
||||||
8 => ['A' => 13],
|
|
||||||
9 => ['A' => 21],
|
|
||||||
10 => ['A' => 34],
|
|
||||||
11 => ['A' => 55],
|
|
||||||
12 => ['A' => 89],
|
|
||||||
];
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[
|
[19.3333333333333, 1],
|
||||||
19.3333333333333,
|
[12, 2],
|
||||||
1,
|
[12, 3],
|
||||||
$baseTestData,
|
[89, 4],
|
||||||
],
|
[0, 5],
|
||||||
[
|
[0, 6],
|
||||||
12,
|
[27.5196899207337, 7],
|
||||||
2,
|
[26.3480971271593, 8],
|
||||||
$baseTestData,
|
[232, 9],
|
||||||
],
|
[757.3333333333330, '10'],
|
||||||
[
|
[694.2222222222220, 11.1],
|
||||||
12,
|
['#VALUE!', 0],
|
||||||
3,
|
['#VALUE!', -1],
|
||||||
$baseTestData,
|
['#VALUE!', 12],
|
||||||
],
|
['#VALUE!', '"X"'],
|
||||||
[
|
|
||||||
89,
|
|
||||||
4,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
5,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
6,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
27.5196899207337,
|
|
||||||
7,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
26.3480971271593,
|
|
||||||
8,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
232,
|
|
||||||
9,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
757.3333333333330,
|
|
||||||
10,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
694.2222222222220,
|
|
||||||
11,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,100 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$baseTestData = [
|
|
||||||
1 => ['A' => 0],
|
|
||||||
2 => ['A' => 1],
|
|
||||||
3 => ['A' => 1],
|
|
||||||
4 => ['A' => 2],
|
|
||||||
5 => ['A' => 3],
|
|
||||||
6 => ['A' => 5],
|
|
||||||
7 => ['A' => 8],
|
|
||||||
8 => ['A' => 13],
|
|
||||||
9 => ['A' => 21],
|
|
||||||
10 => ['A' => 34],
|
|
||||||
11 => ['A' => 55],
|
|
||||||
12 => ['A' => 89],
|
|
||||||
];
|
|
||||||
|
|
||||||
$hiddenRows = [
|
|
||||||
1 => false,
|
|
||||||
2 => true,
|
|
||||||
3 => false,
|
|
||||||
4 => true,
|
|
||||||
5 => false,
|
|
||||||
6 => false,
|
|
||||||
7 => false,
|
|
||||||
8 => true,
|
|
||||||
9 => false,
|
|
||||||
10 => true,
|
|
||||||
11 => true,
|
|
||||||
12 => false,
|
|
||||||
];
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[
|
[21, 101],
|
||||||
21,
|
[5, 102],
|
||||||
$hiddenRows,
|
[5, 103],
|
||||||
101,
|
[55, 104],
|
||||||
$baseTestData,
|
[1, 105],
|
||||||
],
|
[48620, 106],
|
||||||
[
|
[23.1840462387393, 107],
|
||||||
5,
|
[20.7364413533277, 108],
|
||||||
$hiddenRows,
|
[105, 109],
|
||||||
102,
|
[537.5, 110],
|
||||||
$baseTestData,
|
[430, 111],
|
||||||
],
|
|
||||||
[
|
|
||||||
5,
|
|
||||||
$hiddenRows,
|
|
||||||
103,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
55,
|
|
||||||
$hiddenRows,
|
|
||||||
104,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
$hiddenRows,
|
|
||||||
105,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
48620,
|
|
||||||
$hiddenRows,
|
|
||||||
106,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
23.1840462387393,
|
|
||||||
$hiddenRows,
|
|
||||||
107,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
20.7364413533277,
|
|
||||||
$hiddenRows,
|
|
||||||
108,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
105,
|
|
||||||
$hiddenRows,
|
|
||||||
109,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
537.5,
|
|
||||||
$hiddenRows,
|
|
||||||
110,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
430,
|
|
||||||
$hiddenRows,
|
|
||||||
111,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$baseTestData = [
|
|
||||||
1 => ['A' => 123],
|
|
||||||
2 => ['A' => 234],
|
|
||||||
3 => ['A' => '=SUBTOTAL(1, A1:A2)'],
|
|
||||||
4 => ['A' => '=ROMAN(SUBTOTAL(1, A1:A2))'],
|
|
||||||
5 => ['A' => 'This is text containing "=" and "SUBTOTAL("'],
|
|
||||||
6 => ['A' => '=AGGREGATE(1, A1:A2)'],
|
|
||||||
];
|
|
||||||
|
|
||||||
return [
|
|
||||||
[
|
|
||||||
357,
|
|
||||||
9,
|
|
||||||
$baseTestData,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
[50, 5, 15, 30],
|
||||||
|
[52, 5, 15, 30, 2],
|
||||||
|
[53.1, 5.7, 15, 30, 2.4],
|
||||||
|
['#VALUE!', 5.7, 'X', 30, 2.4], // error here conflicts with SUMIF
|
||||||
|
];
|
||||||
|
|
@ -16,19 +16,19 @@ return [
|
||||||
['text'],
|
['text'],
|
||||||
[2],
|
[2],
|
||||||
],
|
],
|
||||||
'=text',
|
'text',
|
||||||
[
|
[
|
||||||
[10],
|
[10],
|
||||||
[100],
|
[100],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
10,
|
'incomplete', // 10,
|
||||||
[
|
[
|
||||||
['"text with quotes"'],
|
['"text with quotes"'],
|
||||||
[2],
|
[2],
|
||||||
],
|
],
|
||||||
'="text with quotes"',
|
'"text with quotes"',
|
||||||
[
|
[
|
||||||
[10],
|
[10],
|
||||||
[100],
|
[100],
|
||||||
|
|
@ -122,20 +122,32 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
157559,
|
157559,
|
||||||
['Jan', 'Jan', 'Jan', 'Jan', 'Feb', 'Feb', 'Feb', 'Feb'],
|
[['Jan'], ['Jan'], ['Jan'], ['Jan'], ['Feb'], ['Feb'], ['Feb'], ['Feb']],
|
||||||
'Feb',
|
'Feb',
|
||||||
[36693, 22100, 53321, 34440, 29889, 50090, 32080, 45500],
|
[[36693], [22100], [53321], [34440], [29889], [50090], [32080], [45500]],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
66582,
|
66582,
|
||||||
['North 1', 'North 2', 'South 1', 'South 2', 'North 1', 'North 2', 'South 1', 'South 2,'],
|
[['North 1'], ['North 2'], ['South 1'], ['South 2'], ['North 1'], ['North 2'], ['South 1'], ['South 2']],
|
||||||
'North 1',
|
'North 1',
|
||||||
[36693, 22100, 53321, 34440, 29889, 50090, 32080, 45500],
|
[[36693], [22100], [53321], [34440], [29889], [50090], [32080], [45500]],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
138772,
|
138772,
|
||||||
['North 1', 'North 2', 'South 1', 'South 2', 'North 1', 'North 2', 'South 1', 'South 2,'],
|
[['North 1'], ['North 2'], ['South 1'], ['South 2'], ['North 1'], ['North 2'], ['South 1'], ['South 2']],
|
||||||
'North ?',
|
'North ?',
|
||||||
[36693, 22100, 53321, 34440, 29889, 50090, 32080, 45500],
|
[[36693], [22100], [53321], [34440], [29889], [50090], [32080], [45500]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#DIV/0!',
|
||||||
|
[['North 1'], ['North 2'], ['South 1'], ['South 2'], ['North 1'], ['North 2'], ['South 1'], ['South 2']],
|
||||||
|
'North ?',
|
||||||
|
[['=3/0'], [22100], [53321], [34440], [29889], [50090], [32080], [45500]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
138772,
|
||||||
|
[['North 1'], ['North 2'], ['South 1'], ['South 2'], ['North 1'], ['North 2'], ['South 1'], ['South 2']],
|
||||||
|
'North ?',
|
||||||
|
[[36693], [22100], ['=3/0'], [34440], [29889], [50090], [32080], [45500]],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,14 @@ return [
|
||||||
[[1, 2], [3, 4]],
|
[[1, 2], [3, 4]],
|
||||||
[[5, 6], [7, 8]],
|
[[5, 6], [7, 8]],
|
||||||
],
|
],
|
||||||
|
['#VALUE!', [1, 2], [5, 6, 4]], // mismatched dimensions
|
||||||
|
[17, [1, 2, 3], [5, 'y', 4]],
|
||||||
|
[17, [1, 2, 3], [5, 0, 4]],
|
||||||
|
[19, [1, 2, 3], [5, 1, 4]],
|
||||||
|
[145, [1, 2, 3], [5, 1, 4], [9, 8, 7]],
|
||||||
|
[61, [1, 2, 3], [5, 1, 4], [9, 8, '="7"']], // string treated as 0
|
||||||
|
[100, ['="1"', 2, 3], [5, 1, 4], [9, 8, 7]], // string treated as 0
|
||||||
|
[100, [null, 2, 3], [5, 1, 4], [9, 8, 7]], // null treated as 0
|
||||||
|
[100, [true, 2, 3], [5, 1, 4], [9, 8, 7]], // true treated as 0
|
||||||
|
[61, [1, 2, 3], [5, 1, 4], [9, 8, true]], // true treated as 0
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue