From 692c5aa5b9741556fbd6aa7b1c8d23481b8cf3a7 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 09:47:56 +0200 Subject: [PATCH 01/39] Return an ExcelException object rather than a string to represent MS Excel formula errors, so that formulae that return string values that do begin with a '#' can be distinguished from actual formula errors --- .../Calculation/Calculation.php | 27 +- src/PhpSpreadsheet/Calculation/DateTime.php | 102 ++--- .../Calculation/ExcelException.php | 114 ++++++ src/PhpSpreadsheet/Calculation/Financial.php | 58 ++- src/PhpSpreadsheet/Calculation/Functions.php | 90 ++--- src/PhpSpreadsheet/Calculation/Logical.php | 6 +- .../Calculation/Statistical.php | 19 +- src/PhpSpreadsheet/Cell/Cell.php | 1 - src/PhpSpreadsheet/Cell/DataType.php | 36 +- src/PhpSpreadsheet/Cell/DataValidator.php | 5 +- src/PhpSpreadsheet/Reader/Xls/ErrorCode.php | 8 +- src/PhpSpreadsheet/Reader/Xlsx.php | 3 +- src/PhpSpreadsheet/Shared/Date.php | 5 +- src/PhpSpreadsheet/Shared/Trend/Trend.php | 3 + src/PhpSpreadsheet/Worksheet/Worksheet.php | 6 +- src/PhpSpreadsheet/Writer/Html.php | 8 + src/PhpSpreadsheet/Writer/Ods/Content.php | 3 +- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 17 +- src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php | 13 +- .../Calculation/CalculationTest.php | 11 +- .../Calculation/Engine/RangeTest.php | 9 +- .../Calculation/ExcelExceptionTest.php | 34 ++ .../Calculation/FinancialTest.php | 359 +++++++++++++----- .../Functions/DateTime/DateDifTest.php | 6 +- .../Functions/DateTime/DateTest.php | 7 +- .../Functions/DateTime/DateValueTest.php | 6 +- .../Functions/DateTime/DayTest.php | 14 +- .../Functions/Engineering/ImDivTest.php | 13 +- .../Functions/Engineering/ImLnTest.php | 13 +- .../Functions/Engineering/ImLog10Test.php | 13 +- .../Functions/Engineering/ImLog2Test.php | 13 +- .../Functions/Engineering/ImPowerTest.php | 13 +- .../Functions/Engineering/ImProductTest.php | 13 +- .../Functions/Engineering/ImSubTest.php | 13 +- .../Functions/Engineering/ImSumTest.php | 13 +- .../Functions/Financial/AccrintMTest.php | 7 +- .../Functions/Financial/AccrintTest.php | 7 +- .../Calculation/Functions/Logical/AndTest.php | 7 +- .../Calculation/Functions/Logical/IfTest.php | 7 +- .../Calculation/Functions/Logical/OrTest.php | 7 +- .../Functions/Statistical/AveDevTest.php | 7 +- .../Calculation/FunctionsTest.php | 28 +- tests/PhpSpreadsheetTests/Cell/CellTest.php | 8 +- .../Writer/Xlsx/StartsWithHashTest.php | 7 +- tests/data/Calculation/DateTime/DATE.php | 16 +- tests/data/Calculation/DateTime/DATEDIF.php | 10 +- tests/data/Calculation/DateTime/DATEVALUE.php | 34 +- tests/data/Calculation/DateTime/DAY.php | 8 +- tests/data/Calculation/Engineering/IMDIV.php | 4 +- tests/data/Calculation/Engineering/IMLN.php | 4 +- .../data/Calculation/Engineering/IMLOG10.php | 4 +- tests/data/Calculation/Engineering/IMLOG2.php | 4 +- .../data/Calculation/Engineering/IMPOWER.php | 4 +- .../Calculation/Engineering/IMPRODUCT.php | 4 +- tests/data/Calculation/Engineering/IMSUB.php | 4 +- tests/data/Calculation/Engineering/IMSUM.php | 6 +- tests/data/Calculation/ExcelException.php | 10 + tests/data/Calculation/Financial/ACCRINT.php | 10 +- tests/data/Calculation/Financial/ACCRINTM.php | 8 +- .../data/Calculation/Financial/COUPDAYBS.php | 8 +- tests/data/Calculation/Financial/COUPDAYS.php | 8 +- .../data/Calculation/Financial/COUPDAYSNC.php | 8 +- tests/data/Calculation/Financial/COUPNCD.php | 10 +- tests/data/Calculation/Financial/COUPNUM.php | 10 +- tests/data/Calculation/Financial/COUPPCD.php | 10 +- tests/data/Calculation/Financial/CUMIPMT.php | 6 +- tests/data/Calculation/Financial/CUMPRINC.php | 6 +- tests/data/Calculation/Financial/DB.php | 6 +- tests/data/Calculation/Financial/DDB.php | 6 +- tests/data/Calculation/Financial/DISC.php | 8 +- tests/data/Calculation/Financial/DOLLARDE.php | 6 +- tests/data/Calculation/Financial/DOLLARFR.php | 6 +- tests/data/Calculation/Financial/EFFECT.php | 4 +- tests/data/Calculation/Financial/FV.php | 4 +- tests/data/Calculation/Financial/INTRATE.php | 8 +- tests/data/Calculation/Financial/IPMT.php | 6 +- tests/data/Calculation/Financial/IRR.php | 9 + tests/data/Calculation/Financial/NOMINAL.php | 4 +- tests/data/Calculation/Financial/NPER.php | 8 +- .../data/Calculation/Financial/PDURATION.php | 8 +- tests/data/Calculation/Financial/PRICE.php | 28 +- .../data/Calculation/Financial/PRICEDISC.php | 2 + tests/data/Calculation/Financial/RATE.php | 6 +- tests/data/Calculation/Financial/RRI.php | 8 +- tests/data/Calculation/Financial/SLN.php | 6 +- tests/data/Calculation/Financial/SYD.php | 6 +- tests/data/Calculation/Financial/XIRR.php | 20 +- tests/data/Calculation/Financial/XNPV.php | 18 +- .../data/Calculation/Functions/ERROR_TYPE.php | 30 +- .../data/Calculation/Functions/ISFORMULA.php | 6 +- tests/data/Calculation/Functions/IS_BLANK.php | 6 +- tests/data/Calculation/Functions/IS_ERR.php | 6 +- tests/data/Calculation/Functions/IS_ERROR.php | 6 +- tests/data/Calculation/Functions/IS_EVEN.php | 64 ++-- .../data/Calculation/Functions/IS_LOGICAL.php | 4 +- tests/data/Calculation/Functions/IS_NA.php | 6 +- .../data/Calculation/Functions/IS_NONTEXT.php | 6 +- .../data/Calculation/Functions/IS_NUMBER.php | 6 +- tests/data/Calculation/Functions/IS_ODD.php | 24 +- tests/data/Calculation/Functions/IS_TEXT.php | 6 +- tests/data/Calculation/Functions/N.php | 10 +- tests/data/Calculation/Functions/TYPE.php | 6 +- tests/data/Calculation/Logical/AND.php | 8 +- tests/data/Calculation/Logical/IF.php | 6 +- tests/data/Calculation/Logical/IFERROR.php | 8 +- tests/data/Calculation/Logical/IFNA.php | 4 +- tests/data/Calculation/Logical/OR.php | 6 +- tests/data/Calculation/Logical/XOR.php | 6 +- tests/data/Calculation/Statistical/AVEDEV.php | 8 +- tests/data/Cell/SetValueExplicit.php | 7 +- 110 files changed, 1218 insertions(+), 553 deletions(-) create mode 100644 src/PhpSpreadsheet/Calculation/ExcelException.php create mode 100644 tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php create mode 100644 tests/data/Calculation/ExcelException.php diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 99260e3bf1..f0649f7665 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -3659,6 +3659,10 @@ private function showValue($value) private function showTypeDetails($value) { if ($this->debugLog->getWriteDebugLog()) { + if ($value instanceof ExcelException) { + return "an Excel {$value->errorName()} Error"; + } + $testArray = Functions::flattenArray($value); if (count($testArray) == 1) { $value = array_pop($testArray); @@ -3677,8 +3681,6 @@ private function showTypeDetails($value) } else { if ($value == '') { return 'an empty string'; - } elseif ($value[0] == '#') { - return 'a ' . $value . ' error'; } $typeString = 'a string'; } @@ -4039,9 +4041,11 @@ private function internalParseFormula($formula, ?Cell $pCell = null) $length = strlen($val); if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/miu', $val, $matches)) { $val = preg_replace('/\s/u', '', $val); + $reference = null; if (isset(self::$phpSpreadsheetFunctions[strtoupper($matches[1])]) || isset(self::$controlFunctions[strtoupper($matches[1])])) { // it's a function $valToUpper = strtoupper($val); } else { + $reference = strtoupper($val); $valToUpper = 'NAME.ERROR('; } // here $matches[1] will contain values like "IF" @@ -4057,7 +4061,7 @@ private function internalParseFormula($formula, ?Cell $pCell = null) } } - $stack->push('Function', $valToUpper, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); + $stack->push('Function', $valToUpper, $reference, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); // tests if the function is closed right after opening $ax = preg_match('/^\s*\)/u', substr($formula, $index + $length)); if ($ax) { @@ -4493,7 +4497,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $pCell = null) $result = $matrixResult->getArray(); } catch (\Exception $ex) { $this->debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); - $result = '#VALUE!'; + $result = ExcelException::VALUE(); } } else { $result = self::FORMULA_STRING_QUOTE . str_replace('""', self::FORMULA_STRING_QUOTE, self::unwrapResult($operand1) . self::unwrapResult($operand2)) . self::FORMULA_STRING_QUOTE; @@ -4551,7 +4555,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $pCell = null) $result = $matrixResult->getArray(); } catch (\Exception $ex) { $this->debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); - $result = '#VALUE!'; + $result = ExcelException::VALUE(); } $this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result)); $stack->push('Value', $result); @@ -4769,6 +4773,13 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $pCell = null) private function validateBinaryOperand(&$operand, &$stack) { + if ($operand instanceof ExcelException) { + $stack->push('Error', $operand); + $this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($operand)); + + return false; + } + if (is_array($operand)) { if ((count($operand, COUNT_RECURSIVE) - count($operand)) == 1) { do { @@ -4793,7 +4804,7 @@ private function validateBinaryOperand(&$operand, &$stack) return false; } elseif (!Shared\StringHelper::convertToNumberIfFraction($operand)) { // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations - $stack->push('Error', '#VALUE!'); + $stack->push('Error', ExcelException::VALUE()); $this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!')); return false; @@ -4992,7 +5003,7 @@ private function executeNumericBinaryOperation($operand1, $operand2, $operation, $result = $matrixResult->getArray(); } catch (\Exception $ex) { $this->debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); - $result = '#VALUE!'; + $result = ExcelException::VALUE(); } } else { if ( @@ -5023,7 +5034,7 @@ private function executeNumericBinaryOperation($operand1, $operand2, $operation, case '/': if ($operand2 == 0) { // Trap for Divide by Zero error - $stack->push('Error', '#DIV/0!'); + $stack->push('Error', ExcelException::DIV0()); $this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails('#DIV/0!')); return false; diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index bfce2a0250..dfd2eff313 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -63,19 +63,22 @@ private static function dateDiff360($startDay, $startMonth, $startYear, $endDay, * * @param mixed $dateValue * - * @return mixed Excel date/time serial value, or string if error + * @return mixed Excel date/time serial value, or ExcelException if error */ public static function getDateValue($dateValue) { if (!is_numeric($dateValue)) { - if ((is_object($dateValue)) && ($dateValue instanceof DateTimeInterface)) { - $dateValue = Date::PHPToExcel($dateValue); - } else { - $saveReturnDateType = Functions::getReturnDateType(); - Functions::setReturnDateType(Functions::RETURNDATE_EXCEL); - $dateValue = self::DATEVALUE($dateValue); - Functions::setReturnDateType($saveReturnDateType); + if (is_object($dateValue)) { + if ($dateValue instanceof DateTimeInterface) { + return Date::PHPToExcel($dateValue); + } + return Functions::VALUE(); } + + $saveReturnDateType = Functions::getReturnDateType(); + Functions::setReturnDateType(Functions::RETURNDATE_EXCEL); + $dateValue = self::DATEVALUE($dateValue); + Functions::setReturnDateType($saveReturnDateType); } return $dateValue; @@ -645,10 +648,12 @@ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') $endDate = Functions::flattenSingleValue($endDate); $unit = strtoupper(Functions::flattenSingleValue($unit)); - if (is_string($startDate = self::getDateValue($startDate))) { + $startDate = self::getDateValue($startDate); + if ($startDate instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($endDate = self::getDateValue($endDate))) { + $endDate = self::getDateValue($endDate); + if ($endDate instanceof ExcelException) { return Functions::VALUE(); } @@ -753,12 +758,11 @@ public static function DAYS($endDate = 0, $startDate = 0) $endDate = Functions::flattenSingleValue($endDate); $startDate = self::getDateValue($startDate); - if (is_string($startDate)) { + if ($startDate instanceof ExcelException) { return Functions::VALUE(); } - $endDate = self::getDateValue($endDate); - if (is_string($endDate)) { + if ($endDate instanceof ExcelException) { return Functions::VALUE(); } @@ -809,10 +813,12 @@ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) $startDate = Functions::flattenSingleValue($startDate); $endDate = Functions::flattenSingleValue($endDate); - if (is_string($startDate = self::getDateValue($startDate))) { + $startDate = self::getDateValue($startDate); + if ($startDate instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($endDate = self::getDateValue($endDate))) { + $endDate = self::getDateValue($endDate); + if ($endDate instanceof ExcelException) { return Functions::VALUE(); } @@ -866,10 +872,12 @@ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) $endDate = Functions::flattenSingleValue($endDate); $method = Functions::flattenSingleValue($method); - if (is_string($startDate = self::getDateValue($startDate))) { + $startDate = self::getDateValue($startDate); + if ($startDate instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($endDate = self::getDateValue($endDate))) { + $endDate = self::getDateValue($endDate); + if ($endDate instanceof ExcelException) { return Functions::VALUE(); } if ($startDate > $endDate) { @@ -963,11 +971,13 @@ public static function NETWORKDAYS($startDate, $endDate, ...$dateArgs) $dateArgs = Functions::flattenArray($dateArgs); // Validate the start and end dates - if (is_string($startDate = $sDate = self::getDateValue($startDate))) { + $startDate = $sDate = self::getDateValue($startDate); + if ($startDate instanceof ExcelException) { return Functions::VALUE(); } $startDate = (float) floor($startDate); - if (is_string($endDate = $eDate = self::getDateValue($endDate))) { + $endDate = $eDate = self::getDateValue($endDate); + if ($endDate instanceof ExcelException) { return Functions::VALUE(); } $endDate = (float) floor($endDate); @@ -996,7 +1006,8 @@ public static function NETWORKDAYS($startDate, $endDate, ...$dateArgs) // Test any extra holiday parameters $holidayCountedArray = []; foreach ($dateArgs as $holidayDate) { - if (is_string($holidayDate = self::getDateValue($holidayDate))) { + $holidayDate = self::getDateValue($holidayDate); + if ($holidayDate instanceof ExcelException) { return Functions::VALUE(); } if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { @@ -1042,7 +1053,8 @@ public static function WORKDAY($startDate, $endDays, ...$dateArgs) // Get the optional days $dateArgs = Functions::flattenArray($dateArgs); - if ((is_string($startDate = self::getDateValue($startDate))) || (!is_numeric($endDays))) { + $startDate = self::getDateValue($startDate); + if (($startDate instanceof ExcelException) || (!is_numeric($endDays))) { return Functions::VALUE(); } $startDate = (float) floor($startDate); @@ -1076,7 +1088,8 @@ public static function WORKDAY($startDate, $endDays, ...$dateArgs) $holidayCountedArray = $holidayDates = []; foreach ($dateArgs as $holidayDate) { if (($holidayDate !== null) && (trim($holidayDate) > '')) { - if (is_string($holidayDate = self::getDateValue($holidayDate))) { + $holidayDate = self::getDateValue($holidayDate); + if ($holidayDate instanceof ExcelException) { return Functions::VALUE(); } if (self::WEEKDAY($holidayDate, 3) < 5) { @@ -1141,9 +1154,8 @@ public static function DAYOFMONTH($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } @@ -1191,9 +1203,8 @@ public static function WEEKDAY($dateValue = 1, $style = 1) } $style = floor($style); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1310,11 +1321,10 @@ public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY) } $method = self::METHODARR[$method]; - $dateValue = self::getDateValue($dateValue); - if (is_string($dateValue)) { + $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); - } - if ($dateValue < 0.0) { + } elseif ($dateValue < 0.0) { return Functions::NAN(); } @@ -1351,9 +1361,8 @@ public static function ISOWEEKNUM($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1383,10 +1392,8 @@ public static function MONTHOFYEAR($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - if (empty($dateValue)) { - $dateValue = 1; - } - if (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1416,9 +1423,8 @@ public static function YEAR($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1456,7 +1462,7 @@ public static function HOUROFDAY($timeValue = 0) } } $timeValue = self::getTimeValue($timeValue); - if (is_string($timeValue)) { + if ($timeValue instanceof ExcelException) { return Functions::VALUE(); } } @@ -1497,7 +1503,7 @@ public static function MINUTE($timeValue = 0) } } $timeValue = self::getTimeValue($timeValue); - if (is_string($timeValue)) { + if ($timeValue instanceof ExcelException) { return Functions::VALUE(); } } @@ -1538,7 +1544,7 @@ public static function SECOND($timeValue = 0) } } $timeValue = self::getTimeValue($timeValue); - if (is_string($timeValue)) { + if ($timeValue instanceof ExcelException) { return Functions::VALUE(); } } @@ -1583,7 +1589,8 @@ public static function EDATE($dateValue = 1, $adjustmentMonths = 0) } $adjustmentMonths = floor($adjustmentMonths); - if (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } @@ -1629,7 +1636,8 @@ public static function EOMONTH($dateValue = 1, $adjustmentMonths = 0) } $adjustmentMonths = floor($adjustmentMonths); - if (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } diff --git a/src/PhpSpreadsheet/Calculation/ExcelException.php b/src/PhpSpreadsheet/Calculation/ExcelException.php new file mode 100644 index 0000000000..a96c587ca6 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/ExcelException.php @@ -0,0 +1,114 @@ + 1, + self::EXCEL_ERROR_DIVISION_BY_ZERO => 2, + self::EXCEL_ERROR_VALUE => 3, + self::EXCEL_ERROR_REFERENCE => 4, + self::EXCEL_ERROR_NAME => 5, + self::EXCEL_ERROR_NUM => 6, + self::EXCEL_ERROR_NA => 7, + self::EXCEL_ERROR_GETTING_DATA => 8, + ]; + + protected const ERROR_TYPES = [ + self::EXCEL_ERROR_NULL => [self::class, 'NULL'], + self::EXCEL_ERROR_DIVISION_BY_ZERO => [self::class, 'DIV0'], + self::EXCEL_ERROR_VALUE => [self::class, 'VALUE'], + self::EXCEL_ERROR_REFERENCE => [self::class, 'REF'], + self::EXCEL_ERROR_NAME => [self::class, 'NAME'], + self::EXCEL_ERROR_NUM => [self::class, 'NUM'], + self::EXCEL_ERROR_NA => [self::class, 'NA'], + self::EXCEL_ERROR_GETTING_DATA => [self::class, 'DATA'], + ]; + + private $errorName; + + private $code; + + private function __construct($errorName) + { + $this->errorName = $errorName; + $this->code = self::ERROR_CODES[$errorName]; + } + + public static function fromErrorName(string $value): self + { + if (!in_array($value, array_keys(self::ERROR_TYPES), true)) { + throw new SpreadsheetException(sprintf('Invalid Excel Error Code "%s"', $value)); + } + + $errorType = self::ERROR_TYPES[$value]; + return $errorType(); + } + + public static function NULL(): self + { + return new self(self::EXCEL_ERROR_NULL); + } + + public static function DIV0(): self + { + return new self(self::EXCEL_ERROR_DIVISION_BY_ZERO); + } + + public static function VALUE(): self + { + return new self(self::EXCEL_ERROR_VALUE); + } + + public static function REF(): self + { + return new self(self::EXCEL_ERROR_REFERENCE); + } + + public static function NAME(): self + { + return new self(self::EXCEL_ERROR_NAME); + } + + public static function NUM(): self + { + return new self(self::EXCEL_ERROR_NUM); + } + + public static function NA(): self + { + return new self(self::EXCEL_ERROR_NA); + } + + public static function DATA(): self + { + return new self(self::EXCEL_ERROR_GETTING_DATA); + } + + public function code(): int + { + return $this->code; + } + + public function errorName(): string + { + return $this->errorName; + } + + public function __toString() + { + return $this->errorName; + } +} diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 5a908aa513..be6a6b549e 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -388,10 +388,12 @@ public static function COUPDAYBS($settlement, $maturity, $frequency, $basis = 0) $frequency = (int) Functions::flattenSingleValue($frequency); $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); - if (is_string($settlement = DateTime::getDateValue($settlement))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -447,10 +449,12 @@ public static function COUPDAYS($settlement, $maturity, $frequency, $basis = 0) $frequency = (int) Functions::flattenSingleValue($frequency); $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); - if (is_string($settlement = DateTime::getDateValue($settlement))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -517,10 +521,12 @@ public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis = 0 $frequency = (int) Functions::flattenSingleValue($frequency); $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); - if (is_string($settlement = DateTime::getDateValue($settlement))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -573,10 +579,12 @@ public static function COUPNCD($settlement, $maturity, $frequency, $basis = 0) $frequency = (int) Functions::flattenSingleValue($frequency); $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); - if (is_string($settlement = DateTime::getDateValue($settlement))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -626,10 +634,12 @@ public static function COUPNUM($settlement, $maturity, $frequency, $basis = 0) $frequency = (int) Functions::flattenSingleValue($frequency); $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); - if (is_string($settlement = DateTime::getDateValue($settlement))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -681,10 +691,12 @@ public static function COUPPCD($settlement, $maturity, $frequency, $basis = 0) $frequency = (int) Functions::flattenSingleValue($frequency); $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); - if (is_string($settlement = DateTime::getDateValue($settlement))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -1584,10 +1596,10 @@ public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) private static function validatePrice($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis) { - if (is_string($settlement)) { + if ($settlement instanceof ExcelException) { return Functions::VALUE(); } - if (is_string($maturity)) { + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } if (!is_numeric($rate)) { @@ -1622,7 +1634,7 @@ public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $settlement = DateTime::getDateValue($settlement); $maturity = DateTime::getDateValue($maturity); $rslt = self::validatePrice($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis); - if ($rslt) { + if ($rslt instanceof ExcelException) { return $rslt; } $rate = (float) $rate; @@ -2066,7 +2078,12 @@ public static function TBILLPRICE($settlement, $maturity, $discount) $maturity = Functions::flattenSingleValue($maturity); $discount = Functions::flattenSingleValue($discount); - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $settlement = DateTime::getDateValue($settlement); + if ($settlement instanceof ExcelException) { + return Functions::VALUE(); + } + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -2315,9 +2332,12 @@ private static function validateXnpv($rate, $values, $dates) if ($valCount > 1 && ((min($values) > 0) || (max($values) < 0))) { return Functions::NAN(); } - $date0 = DateTime::getDateValue($dates[0]); - if (is_string($date0)) { - return Functions::VALUE(); + + foreach($dates as $date) { + $date = DateTime::getDateValue($date); + if ($date instanceof ExcelException) { + return Functions::VALUE(); + } } return ''; diff --git a/src/PhpSpreadsheet/Calculation/Functions.php b/src/PhpSpreadsheet/Calculation/Functions.php index 2e8a7ecfcc..456bfedbaa 100644 --- a/src/PhpSpreadsheet/Calculation/Functions.php +++ b/src/PhpSpreadsheet/Calculation/Functions.php @@ -2,7 +2,9 @@ namespace PhpOffice\PhpSpreadsheet\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Cell; +use PhpOffice\PhpSpreadsheet\Reader\Xls\ErrorCode; class Functions { @@ -147,11 +149,11 @@ public static function DUMMY() /** * DIV0. * - * @return string #Not Yet Implemented + * Returns the error value #DIV/0 */ - public static function DIV0() + public static function DIV0(): ExcelException { - return self::$errorCodes['divisionbyzero']; + return ExcelException::DIV0(); } /** @@ -162,72 +164,60 @@ public static function DIV0() * * Returns the error value #N/A * #N/A is the error value that means "no value is available." - * - * @return string #N/A! */ - public static function NA() + public static function NA(): ExcelException { - return self::$errorCodes['na']; + return ExcelException::NA(); } /** * NaN. * * Returns the error value #NUM! - * - * @return string #NUM! */ - public static function NAN() + public static function NAN(): ExcelException { - return self::$errorCodes['num']; + return ExcelException::NUM(); } /** * NAME. * * Returns the error value #NAME? - * - * @return string #NAME? */ - public static function NAME() + public static function NAME(): ExcelException { - return self::$errorCodes['name']; + return ExcelException::NAME(); } /** * REF. * * Returns the error value #REF! - * - * @return string #REF! */ - public static function REF() + public static function REF(): ExcelException { - return self::$errorCodes['reference']; + return ExcelException::REF(); } /** * NULL. * * Returns the error value #NULL! - * - * @return string #NULL! */ - public static function null() + public static function null(): ExcelException { - return self::$errorCodes['null']; + return ExcelException::NULL(); } /** * VALUE. * * Returns the error value #VALUE! - * - * @return string #VALUE! */ - public static function VALUE() + public static function VALUE(): ExcelException { - return self::$errorCodes['value']; + return ExcelException::VALUE(); } public static function isMatrixValue($idx) @@ -278,18 +268,14 @@ public static function ifCondition($condition) * * @param mixed $value Value to check * - * @return bool + * @return int|ExcelException */ public static function errorType($value = '') { $value = self::flattenSingleValue($value); - $i = 1; - foreach (self::$errorCodes as $errorCode) { - if ($value === $errorCode) { - return $i; - } - ++$i; + if ($value instanceof ExcelException) { + return $value->code(); } return self::NA(); @@ -336,11 +322,11 @@ public static function isError($value = '') { $value = self::flattenSingleValue($value); - if (!is_string($value)) { - return false; + if ($value instanceof ExcelException) { + return true; } - return in_array($value, self::$errorCodes); + return false; } /** @@ -354,7 +340,11 @@ public static function isNa($value = '') { $value = self::flattenSingleValue($value); - return $value === self::NA(); + if (!is_object($value) || !($value instanceof ExcelException)) { + return false; + } + + return $value == self::NA(); } /** @@ -362,7 +352,7 @@ public static function isNa($value = '') * * @param mixed $value Value to check * - * @return bool|string + * @return bool|ExcelException */ public static function isEven($value = null) { @@ -370,6 +360,8 @@ public static function isEven($value = null) if ($value === null) { return self::NAME(); + } elseif ($value instanceof ExcelException) { + return $value; } elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { return self::VALUE(); } @@ -382,7 +374,7 @@ public static function isEven($value = null) * * @param mixed $value Value to check * - * @return bool|string + * @return bool|ExcelException */ public static function isOdd($value = null) { @@ -390,6 +382,8 @@ public static function isOdd($value = null) if ($value === null) { return self::NAME(); + } elseif ($value instanceof ExcelException) { + return $value; } elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { return self::VALUE(); } @@ -440,7 +434,7 @@ public static function isText($value = null) { $value = self::flattenSingleValue($value); - return is_string($value) && !self::isError($value); + return is_string($value); } /** @@ -484,9 +478,9 @@ public static function n($value = null) return $value; case 'boolean': return (int) $value; - case 'string': + case 'object': // Errors - if ((strlen($value) > 0) && ($value[0] == '#')) { + if ($value instanceof ExcelException) { return $value; } @@ -513,7 +507,12 @@ public static function n($value = null) */ public static function TYPE($value = null) { + if ($value instanceof ExcelException) { + return 16; + } + $value = self::flattenArrayIndexed($value); + if (is_array($value) && (count($value) > 1)) { end($value); $a = key($value); @@ -537,11 +536,6 @@ public static function TYPE($value = null) } elseif (is_array($value)) { return 64; } elseif (is_string($value)) { - // Errors - if ((strlen($value) > 0) && ($value[0] == '#')) { - return 16; - } - return 2; } diff --git a/src/PhpSpreadsheet/Calculation/Logical.php b/src/PhpSpreadsheet/Calculation/Logical.php index 69c543cef9..8ffbe5c274 100644 --- a/src/PhpSpreadsheet/Calculation/Logical.php +++ b/src/PhpSpreadsheet/Calculation/Logical.php @@ -94,7 +94,7 @@ public static function logicalAnd(...$args) $argCount = count($args); $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { + if ($returnValue instanceof ExcelException) { return $returnValue; } @@ -134,7 +134,7 @@ public static function logicalOr(...$args) }); $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { + if ($returnValue instanceof ExcelException) { return $returnValue; } @@ -175,7 +175,7 @@ public static function logicalXor(...$args) }); $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { + if ($returnValue instanceof ExcelException) { return $returnValue; } diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 19f40f2d4a..3e0bc806cc 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -581,14 +581,20 @@ public static function AVEDEV(...$args) $returnValue = 0; $aMean = self::AVERAGE(...$args); - if ($aMean === Functions::DIV0()) { - return Functions::NAN(); - } elseif ($aMean === Functions::VALUE()) { - return Functions::VALUE(); + if ($aMean instanceof ExcelException) { + if ($aMean === Functions::DIV0()) { + return Functions::NAN(); + } elseif ($aMean === Functions::VALUE()) { + return Functions::VALUE(); + } + return $aMean; } $aCount = 0; foreach ($aArgs as $k => $arg) { + if ($arg instanceof ExcelException) { + return $arg; + } $arg = self::testAcceptedBoolean($arg, $k); // Is it a numeric value? // Strings containing numeric values are only counted if they are string literals (not cell values) @@ -628,6 +634,9 @@ public static function AVERAGE(...$args) // Loop through arguments foreach (Functions::flattenArrayIndexed($args) as $k => $arg) { + if ($arg instanceof ExcelException) { + return $arg; + } $arg = self::testAcceptedBoolean($arg, $k); // Is it a numeric value? // Strings containing numeric values are only counted if they are string literals (not cell values) @@ -1416,7 +1425,7 @@ public static function DEVSQ(...$args) $returnValue = null; $aMean = self::AVERAGE($aArgs); - if ($aMean != Functions::DIV0()) { + if (!($aMean instanceof ExcelException)) { $aCount = -1; foreach ($aArgs as $k => $arg) { // Is it a numeric value? diff --git a/src/PhpSpreadsheet/Cell/Cell.php b/src/PhpSpreadsheet/Cell/Cell.php index 5dee411b5f..63349603f3 100644 --- a/src/PhpSpreadsheet/Cell/Cell.php +++ b/src/PhpSpreadsheet/Cell/Cell.php @@ -268,7 +268,6 @@ public function getCalculatedValue($resetLog = true) } elseif (strpos($ex->getMessage(), 'undefined name') !== false) { return \PhpOffice\PhpSpreadsheet\Calculation\Functions::NAME(); } - throw new \PhpOffice\PhpSpreadsheet\Calculation\Exception( $this->getWorksheet()->getTitle() . '!' . $this->getCoordinate() . ' -> ' . $ex->getMessage() ); diff --git a/src/PhpSpreadsheet/Cell/DataType.php b/src/PhpSpreadsheet/Cell/DataType.php index ba03579178..fdee897a2b 100644 --- a/src/PhpSpreadsheet/Cell/DataType.php +++ b/src/PhpSpreadsheet/Cell/DataType.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Cell; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\Shared\StringHelper; @@ -17,21 +18,6 @@ class DataType const TYPE_INLINE = 'inlineStr'; const TYPE_ERROR = 'e'; - /** - * List of error codes. - * - * @var array - */ - private static $errorCodes = [ - '#NULL!' => 0, - '#DIV/0!' => 1, - '#VALUE!' => 2, - '#REF!' => 3, - '#NAME?' => 4, - '#NUM!' => 5, - '#N/A' => 6, - ]; - /** * Get list of error codes. * @@ -39,7 +25,7 @@ class DataType */ public static function getErrorCodes() { - return self::$errorCodes; + return ExcelException::ERROR_CODES; } /** @@ -66,20 +52,22 @@ public static function checkString($pValue) } /** - * Check a value that it is a valid error code. + * Check that a value is a valid error object. * - * @param mixed $pValue Value to sanitize to an Excel error code + * @param ExcelException|string $errorCode Value to sanitize as an Excel error object * - * @return string Sanitized value + * @return ExcelException Sanitized value */ - public static function checkErrorCode($pValue) + public static function checkErrorCode($errorCode): ExcelException { - $pValue = (string) $pValue; + if ($errorCode instanceof ExcelException) { + return $errorCode; + } - if (!isset(self::$errorCodes[$pValue])) { - $pValue = '#NULL!'; + if (!isset(ExcelException::ERROR_CODES[$errorCode])) { + $errorCode = ExcelException::NULL(); } - return $pValue; + return $errorCode; } } diff --git a/src/PhpSpreadsheet/Cell/DataValidator.php b/src/PhpSpreadsheet/Cell/DataValidator.php index 430d81b96e..b6b43dca4d 100644 --- a/src/PhpSpreadsheet/Cell/DataValidator.php +++ b/src/PhpSpreadsheet/Cell/DataValidator.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Cell; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Exception; @@ -65,7 +66,9 @@ private function isValueInList(Cell $cell) try { $result = $calculation->calculateFormula($matchFormula, $cell->getCoordinate(), $cell); - return $result !== Functions::NA(); + if ($result instanceof ExcelException) { + return $result != Functions::NA(); + } } catch (Exception $ex) { return false; } diff --git a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php index 7daf7230ff..50da530f91 100644 --- a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php +++ b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php @@ -2,6 +2,9 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xls; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; +use PhpOffice\PhpSpreadsheet\Exception; + class ErrorCode { protected static $map = [ @@ -19,12 +22,13 @@ class ErrorCode * * @param int $code * - * @return bool|string + * @return bool|ExcelException + * @throws Exception */ public static function lookup($code) { if (isset(self::$map[$code])) { - return self::$map[$code]; + return ExcelException::fromErrorName(self::$map[$code]); } return false; diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 73f9185214..7906958571 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\Hyperlink; use PhpOffice\PhpSpreadsheet\DefinedName; @@ -250,7 +251,7 @@ private static function castToBoolean($c) private static function castToError($c) { - return isset($c->v) ? (string) $c->v : null; + return isset($c->v) ? ExcelException::fromErrorName((string) $c->v) : null; } private static function castToString($c) diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 180a71596d..d065a7336a 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -5,6 +5,7 @@ use DateTimeInterface; use DateTimeZone; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; @@ -438,13 +439,13 @@ public static function stringToExcel($dateValue) $dateValueNew = DateTime::DATEVALUE($dateValue); - if ($dateValueNew === Functions::VALUE()) { + if ($dateValueNew instanceof ExcelException && $dateValueNew == Functions::VALUE()) { return false; } if (strpos($dateValue, ':') !== false) { $timeValue = DateTime::TIMEVALUE($dateValue); - if ($timeValue === Functions::VALUE()) { + if ($timeValue instanceof ExcelException && $timeValue == Functions::VALUE()) { return false; } $dateValueNew += $timeValue; diff --git a/src/PhpSpreadsheet/Shared/Trend/Trend.php b/src/PhpSpreadsheet/Shared/Trend/Trend.php index 1b7b390107..172428f186 100644 --- a/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -48,6 +48,9 @@ class Trend */ private static $trendCache = []; + /* + * @return BestFit|false + */ public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [], $xValues = [], $const = true) { // Calculate number of points in each dataset diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 19833b71e5..62ebb02b75 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -4,6 +4,7 @@ use ArrayObject; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\DataType; @@ -2522,7 +2523,10 @@ public function rangeToArray($pRange, $nullValue = null, $calculateFormulas = tr $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); } else { if ($calculateFormulas) { - $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); + $calculatedValue = $cell->getCalculatedValue(); + $returnValue[$rRef][$cRef] = $calculatedValue instanceof ExcelException + ? $calculatedValue->errorName() + : $calculatedValue; } else { $returnValue[$rRef][$cRef] = $cell->getValue(); } diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index 5c21b3a94e..60cd64e8c1 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Chart\Chart; @@ -157,6 +158,10 @@ public function save($pFilename): void // Open file $this->openFileHandle($pFilename); + if ($this->preCalculateFormulas) { + $this->spreadsheet->getCalculationEngine()->clearCalculationCache(); + } + // Write html fwrite($this->fileHandle, $this->generateHTMLAll()); @@ -1316,6 +1321,9 @@ private function generateRowCellDataValue($pSheet, $cell, &$cellData): void $this->generateRowCellDataValueRich($cell, $cellData); } else { $origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue(); + if ($origData instanceof ExcelException) { + $origData = $origData->errorName(); + } $cellData = NumberFormat::toFormattedString( $origData, $pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(), diff --git a/src/PhpSpreadsheet/Writer/Ods/Content.php b/src/PhpSpreadsheet/Writer/Ods/Content.php index 96e66850df..16abd273d6 100644 --- a/src/PhpSpreadsheet/Writer/Ods/Content.php +++ b/src/PhpSpreadsheet/Writer/Ods/Content.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Ods; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\DataType; @@ -215,7 +216,7 @@ private function writeCells(XMLWriter $objWriter, Row $row): void $objWriter->writeAttribute('office:value-type', 'string'); } $objWriter->writeAttribute('office:value', $formulaValue); - $objWriter->writeElement('text:p', $formulaValue); + $objWriter->writeElement('text:p', $formulaValue instanceof ExcelException ? $formulaValue->errorName() :$formulaValue); break; case DataType::TYPE_INLINE: diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index a1c258c042..cb8746ee36 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Xls; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\Cell\DataValidation; @@ -832,18 +833,22 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) if (isset($calculatedValue)) { // Since we can't yet get the data type of the calculated value, // we use best effort to determine data type - if (is_bool($calculatedValue)) { + if ($calculatedValue instanceof ExcelException) { + $errorCodes = DataType::getErrorCodes(); + if (isset($errorCodes[$calculatedValue->errorName()])) { + // Error value + $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); + } else { + // We are really not supposed to reach here + $num = pack('d', 0x00); } + } elseif (is_bool($calculatedValue)) { // Boolean value $num = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF); } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { // Numeric value $num = pack('d', $calculatedValue); } elseif (is_string($calculatedValue)) { - $errorCodes = DataType::getErrorCodes(); - if (isset($errorCodes[$calculatedValue])) { - // Error value - $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); - } elseif ($calculatedValue === '') { + if ($calculatedValue === '') { // Empty string (and BIFF8) $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); } else { diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index b6a6fc390b..753e537738 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; +use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\RichText\RichText; @@ -1118,12 +1120,11 @@ private function writeCellError(XMLWriter $objWriter, string $mappedType, string private function writeCellFormula(XMLWriter $objWriter, string $cellValue, Cell $pCell): void { $calculatedValue = $this->getParentWriter()->getPreCalculateFormulas() ? $pCell->getCalculatedValue() : $cellValue; - if (is_string($calculatedValue)) { - if (\PhpOffice\PhpSpreadsheet\Calculation\Functions::isError($calculatedValue)) { - $this->writeCellError($objWriter, 'e', $cellValue, $calculatedValue); + if ($calculatedValue instanceof ExcelException) { + $this->writeCellError($objWriter, 'e', $cellValue, $calculatedValue->errorName()); - return; - } + return; + } elseif (is_string($calculatedValue)) { $objWriter->writeAttribute('t', 'str'); } elseif (is_bool($calculatedValue)) { $objWriter->writeAttribute('t', 'b'); @@ -1199,7 +1200,7 @@ private function writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet break; case 'e': // Error - $this->writeCellError($objWriter, $mappedType, $cellValue); + $this->writeCellError($objWriter, $mappedType, $cellValue instanceof ExcelException ? $cellValue->errorName() : Functions::null()); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php index 8e339207f5..54881f9512 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php @@ -3,6 +3,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; @@ -371,9 +372,11 @@ public function testUnknownFunction(): void $sheet->setCellValue('A2', '=mode.gzorg(1)'); $sheet->setCellValue('A3', '=gzorg(1,2)'); $sheet->setCellValue('A4', '=3+IF(gzorg(),1,2)'); - self::assertEquals('#NAME?', $sheet->getCell('A1')->getCalculatedValue()); - self::assertEquals('#NAME?', $sheet->getCell('A2')->getCalculatedValue()); - self::assertEquals('#NAME?', $sheet->getCell('A3')->getCalculatedValue()); - self::assertEquals('#NAME?', $sheet->getCell('A4')->getCalculatedValue()); + $sheet->setCellValue('A5', '=3+IFERROR(gzorg(),2)'); + self::assertEquals(ExcelException::NAME(), $sheet->getCell('A1')->getCalculatedValue()); + self::assertEquals(ExcelException::NAME(), $sheet->getCell('A2')->getCalculatedValue()); + self::assertEquals(ExcelException::NAME(), $sheet->getCell('A3')->getCalculatedValue()); + self::assertEquals(ExcelException::NAME(), $sheet->getCell('A4')->getCalculatedValue()); + self::assertEquals(5, $sheet->getCell('A5')->getCalculatedValue()); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php b/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php index 4f1ff39735..6e1951af78 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Engine; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\NamedRange; use PhpOffice\PhpSpreadsheet\Spreadsheet; @@ -37,7 +38,13 @@ public function testRangeEvaluation(string $formula, $expectedResult): void $workSheet->setCellValue('E1', $formula); $actualRresult = $workSheet->getCell('E1')->getCalculatedValue(); - self::assertSame($expectedResult, $actualRresult); + + if ($expectedResult instanceof ExcelException) { + // We can't use assertSame when comparing objects, unless they're the same instance + self::assertEquals($expectedResult, $actualRresult); + } else { + self::assertSame($expectedResult, $actualRresult); + } } public function providerRangeEvaluation() diff --git a/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php new file mode 100644 index 0000000000..76045a175c --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php @@ -0,0 +1,34 @@ +expectException(SpreadsheetException::class); + $result = ExcelException::fromErrorName('#MARK!'); + } +} diff --git a/tests/PhpSpreadsheetTests/Calculation/FinancialTest.php b/tests/PhpSpreadsheetTests/Calculation/FinancialTest.php index e80ef35b66..cd08c14824 100644 --- a/tests/PhpSpreadsheetTests/Calculation/FinancialTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/FinancialTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testAMORDEGRC($expectedResult, ...$args): void { $result = Financial::AMORDEGRC(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerAMORDEGRC() @@ -37,7 +42,12 @@ public function providerAMORDEGRC() public function testAMORLINC($expectedResult, ...$args): void { $result = Financial::AMORLINC(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerAMORLINC() @@ -53,7 +63,12 @@ public function providerAMORLINC() public function testCOUPDAYBS($expectedResult, ...$args): void { $result = Financial::COUPDAYBS(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCOUPDAYBS() @@ -69,7 +84,12 @@ public function providerCOUPDAYBS() public function testCOUPDAYS($expectedResult, ...$args): void { $result = Financial::COUPDAYS(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCOUPDAYS() @@ -85,7 +105,12 @@ public function providerCOUPDAYS() public function testCOUPDAYSNC($expectedResult, ...$args): void { $result = Financial::COUPDAYSNC(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCOUPDAYSNC() @@ -101,7 +126,12 @@ public function providerCOUPDAYSNC() public function testCOUPNCD($expectedResult, ...$args): void { $result = Financial::COUPNCD(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCOUPNCD() @@ -117,7 +147,12 @@ public function providerCOUPNCD() public function testCOUPNUM($expectedResult, ...$args): void { $result = Financial::COUPNUM(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCOUPNUM() @@ -133,7 +168,12 @@ public function providerCOUPNUM() public function testCOUPPCD($expectedResult, ...$args): void { $result = Financial::COUPPCD(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCOUPPCD() @@ -149,7 +189,12 @@ public function providerCOUPPCD() public function testCUMIPMT($expectedResult, ...$args): void { $result = Financial::CUMIPMT(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCUMIPMT() @@ -165,7 +210,12 @@ public function providerCUMIPMT() public function testCUMPRINC($expectedResult, ...$args): void { $result = Financial::CUMPRINC(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerCUMPRINC() @@ -181,7 +231,12 @@ public function providerCUMPRINC() public function testDB($expectedResult, ...$args): void { $result = Financial::DB(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDB() @@ -197,7 +252,12 @@ public function providerDB() public function testDDB($expectedResult, ...$args): void { $result = Financial::DDB(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDDB() @@ -213,7 +273,12 @@ public function providerDDB() public function testDISC($expectedResult, ...$args): void { $result = Financial::DISC(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDISC() @@ -229,7 +294,12 @@ public function providerDISC() public function testDOLLARDE($expectedResult, ...$args): void { $result = Financial::DOLLARDE(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDOLLARDE() @@ -245,7 +315,12 @@ public function providerDOLLARDE() public function testDOLLARFR($expectedResult, ...$args): void { $result = Financial::DOLLARFR(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDOLLARFR() @@ -261,7 +336,12 @@ public function providerDOLLARFR() public function testEFFECT($expectedResult, ...$args): void { $result = Financial::EFFECT(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerEFFECT() @@ -277,7 +357,12 @@ public function providerEFFECT() public function testFV($expectedResult, ...$args): void { $result = Financial::FV(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerFV() @@ -293,7 +378,12 @@ public function providerFV() public function testFVSCHEDULE($expectedResult, ...$args): void { $result = Financial::FVSCHEDULE(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerFVSCHEDULE() @@ -309,7 +399,12 @@ public function providerFVSCHEDULE() public function testINTRATE($expectedResult, ...$args): void { $result = Financial::INTRATE(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerINTRATE() @@ -325,7 +420,12 @@ public function providerINTRATE() public function testIPMT($expectedResult, ...$args): void { $result = Financial::IPMT(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerIPMT() @@ -341,7 +441,12 @@ public function providerIPMT() public function testIRR($expectedResult, ...$args): void { $result = Financial::IRR(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerIRR() @@ -357,7 +462,12 @@ public function providerIRR() public function testISPMT($expectedResult, ...$args): void { $result = Financial::ISPMT(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerISPMT() @@ -373,7 +483,12 @@ public function providerISPMT() public function testMIRR($expectedResult, ...$args): void { $result = Financial::MIRR(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerMIRR() @@ -389,7 +504,12 @@ public function providerMIRR() public function testNOMINAL($expectedResult, ...$args): void { $result = Financial::NOMINAL(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerNOMINAL() @@ -405,7 +525,12 @@ public function providerNOMINAL() public function testNPER($expectedResult, ...$args): void { $result = Financial::NPER(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerNPER() @@ -421,7 +546,12 @@ public function providerNPER() public function testNPV($expectedResult, ...$args): void { $result = Financial::NPV(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerNPV() @@ -429,6 +559,27 @@ public function providerNPV() return require 'tests/data/Calculation/Financial/NPV.php'; } + /** + * @dataProvider providerPDURATION + * + * @param mixed $expectedResult + */ + public function testPDURATION($expectedResult, array $args): void + { + $result = Financial::PDURATION(...$args); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } + } + + public function providerPDURATION() + { + return require 'tests/data/Calculation/Financial/PDURATION.php'; + } + /** * @dataProvider providerPRICE * @@ -437,7 +588,12 @@ public function providerNPV() public function testPRICE($expectedResult, ...$args): void { $result = Financial::PRICE(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-7); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-7); + } } public function providerPRICE() @@ -456,7 +612,12 @@ public function testPRICE3($expectedResult, ...$args): void // agree with published algorithm, LibreOffice, and Gnumeric. // They do not agree with Excel. $result = Financial::PRICE(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-7); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-7); + } } public function providerPRICE3() @@ -472,7 +633,12 @@ public function providerPRICE3() public function testPRICEDISC($expectedResult, array $args): void { $result = Financial::PRICEDISC(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerPRICEDISC() @@ -488,7 +654,12 @@ public function providerPRICEDISC() public function testPV($expectedResult, array $args): void { $result = Financial::PV(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerPV() @@ -504,7 +675,12 @@ public function providerPV() public function testRATE($expectedResult, ...$args): void { $result = Financial::RATE(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerRATE() @@ -513,116 +689,115 @@ public function providerRATE() } /** - * @dataProvider providerXIRR + * @dataProvider providerRRI * * @param mixed $expectedResult - * @param mixed $message */ - public function testXIRR($expectedResult, $message, ...$args): void + public function testRRI($expectedResult, array $args): void { - $result = Financial::XIRR(...$args); - if (is_numeric($result) && is_numeric($expectedResult)) { - if ($expectedResult != 0) { - $frac = $result / $expectedResult; - if ($frac > 0.999999 && $frac < 1.000001) { - $result = $expectedResult; - } - } + $result = Financial::RRI(...$args); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); } - self::assertEquals($expectedResult, $result, $message); } - public function providerXIRR() + public function providerRRI() { - return require 'tests/data/Calculation/Financial/XIRR.php'; + return require 'tests/data/Calculation/Financial/RRI.php'; } /** - * @dataProvider providerXNPV + * @dataProvider providerSLN * * @param mixed $expectedResult - * @param mixed $message */ - public function testXNPV($expectedResult, $message, ...$args): void + public function testSLN($expectedResult, array $args): void { - $result = Financial::XNPV(...$args); - if (is_numeric($result) && is_numeric($expectedResult)) { - if ($expectedResult != 0) { - $frac = $result / $expectedResult; - if ($frac > 0.999999 && $frac < 1.000001) { - $result = $expectedResult; - } - } + $result = Financial::SLN(...$args); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); } - self::assertEquals($expectedResult, $result, $message); } - public function providerXNPV() + public function providerSLN() { - return require 'tests/data/Calculation/Financial/XNPV.php'; + return require 'tests/data/Calculation/Financial/SLN.php'; } /** - * @dataProvider providerPDURATION + * @dataProvider providerSYD * * @param mixed $expectedResult */ - public function testPDURATION($expectedResult, array $args): void - { - $result = Financial::PDURATION(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); - } - - public function providerPDURATION() + public function testSYD($expectedResult, array $args): void { - return require 'tests/data/Calculation/Financial/PDURATION.php'; - } + $result = Financial::SYD(...$args); - /** - * @dataProvider providerRRI - * - * @param mixed $expectedResult - */ - public function testRRI($expectedResult, array $args): void - { - $result = Financial::RRI(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } - public function providerRRI() + public function providerSYD() { - return require 'tests/data/Calculation/Financial/RRI.php'; + return require 'tests/data/Calculation/Financial/SYD.php'; } /** - * @dataProvider providerSLN + * @dataProvider providerXIRR * * @param mixed $expectedResult + * @param mixed $message */ - public function testSLN($expectedResult, array $args): void + public function testXIRR($expectedResult, $message, ...$args): void { - $result = Financial::SLN(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + $result = Financial::XIRR(...$args); + if (is_numeric($result) && is_numeric($expectedResult)) { + if ($expectedResult != 0) { + $frac = $result / $expectedResult; + if ($frac > 0.999999 && $frac < 1.000001) { + $result = $expectedResult; + } + } + } + self::assertEquals($expectedResult, $result, $message); } - public function providerSLN() + public function providerXIRR() { - return require 'tests/data/Calculation/Financial/SLN.php'; + return require 'tests/data/Calculation/Financial/XIRR.php'; } /** - * @dataProvider providerSYD + * @dataProvider providerXNPV * * @param mixed $expectedResult + * @param mixed $message */ - public function testSYD($expectedResult, array $args): void + public function testXNPV($expectedResult, $message, ...$args): void { - $result = Financial::SYD(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + $result = Financial::XNPV(...$args); + if (is_numeric($result) && is_numeric($expectedResult)) { + if ($expectedResult != 0) { + $frac = $result / $expectedResult; + if ($frac > 0.999999 && $frac < 1.000001) { + $result = $expectedResult; + } + } + } + self::assertEquals($expectedResult, $result, $message); } - public function providerSYD() + public function providerXNPV() { - return require 'tests/data/Calculation/Financial/SYD.php'; + return require 'tests/data/Calculation/Financial/XNPV.php'; } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php index db8e29a1f7..c873ccfbe6 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php @@ -27,7 +27,11 @@ protected function setUp(): void public function testDATEDIF($expectedResult, $startDate, $endDate, $unit): void { $result = DateTime::DATEDIF($startDate, $endDate, $unit); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDATEDIF() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php index 48f7cfd7ec..c6af9e4482 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php @@ -27,7 +27,12 @@ protected function setUp(): void public function testDATE($expectedResult, $year, $month, $day): void { $result = DateTime::DATE($year, $month, $day); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDATE() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php index 51e4f7c0cf..164122bdc8 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php @@ -26,7 +26,11 @@ protected function setUp(): void public function testDATEVALUE($expectedResult, $dateValue): void { $result = DateTime::DATEVALUE($dateValue); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerDATEVALUE() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php index 482e068d7e..8f4a9dbdd2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php @@ -42,12 +42,22 @@ protected function tearDown(): void public function testDAY($expectedResultExcel, $expectedResultOpenOffice, $dateTimeValue): void { $resultExcel = DateTime::DAYOFMONTH($dateTimeValue); - self::assertEqualsWithDelta($expectedResultExcel, $resultExcel, 1E-8); + + if (is_object($expectedResultExcel)) { + self::assertEquals($expectedResultExcel, $resultExcel); + } else { + self::assertEqualsWithDelta($expectedResultExcel, $resultExcel, 1E-8); + } Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE); $resultOpenOffice = DateTime::DAYOFMONTH($dateTimeValue); - self::assertEqualsWithDelta($expectedResultOpenOffice, $resultOpenOffice, 1E-8); + + if (is_object($expectedResultOpenOffice)) { + self::assertEquals($expectedResultOpenOffice, $resultOpenOffice); + } else { + self::assertEqualsWithDelta($expectedResultOpenOffice, $resultOpenOffice, 1E-8); + } } public function providerDAY() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php index 2bc9161908..d429e58f8a 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php @@ -35,10 +35,15 @@ protected function tearDown(): void public function testIMDIV($expectedResult, ...$args): void { $result = Engineering::IMDIV(...$args); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMDIV() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php index 3e27097518..4875b310b1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php @@ -36,10 +36,15 @@ protected function tearDown(): void public function testIMLN($expectedResult, $value): void { $result = Engineering::IMLN($value); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMLN() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php index 2a4db7fbd7..fe4e821b31 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php @@ -36,10 +36,15 @@ protected function tearDown(): void public function testIMLOG10($expectedResult, $value): void { $result = Engineering::IMLOG10($value); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMLOG10() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php index 53b302dda0..76207492c9 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php @@ -36,10 +36,15 @@ protected function tearDown(): void public function testIMLOG2($expectedResult, $value): void { $result = Engineering::IMLOG2($value); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMLOG2() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php index 41e528780c..1f72895032 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php @@ -35,10 +35,15 @@ protected function tearDown(): void public function testIMPOWER($expectedResult, ...$args): void { $result = Engineering::IMPOWER(...$args); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMPOWER() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php index 43495739b8..77866824fe 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php @@ -35,10 +35,15 @@ protected function tearDown(): void public function testIMPRODUCT($expectedResult, ...$args): void { $result = Engineering::IMPRODUCT(...$args); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMPRODUCT() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php index 79286120f2..82713576ae 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php @@ -35,10 +35,15 @@ protected function tearDown(): void public function testIMSUB($expectedResult, ...$args): void { $result = Engineering::IMSUB(...$args); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMSUB() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php index 8abc363881..6fd1ce6f9e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php @@ -35,10 +35,15 @@ protected function tearDown(): void public function testIMSUM($expectedResult, ...$args): void { $result = Engineering::IMSUM(...$args); - self::assertTrue( - $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), - $this->complexAssert->getErrorMessage() - ); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertTrue( + $this->complexAssert->assertComplexEquals($expectedResult, $result, self::COMPLEX_PRECISION), + $this->complexAssert->getErrorMessage() + ); + } } public function providerIMSUM() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintMTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintMTest.php index 597db5c2cf..aeb0821bee 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintMTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintMTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testACCRINTM($expectedResult, ...$args): void { $result = Financial::ACCRINTM(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerACCRINTM() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintTest.php index edb792305d..fb93dc4e91 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AccrintTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testACCRINT($expectedResult, ...$args): void { $result = Financial::ACCRINT(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerACCRINT() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AndTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AndTest.php index d315e82a52..480556caa3 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AndTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AndTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testAND($expectedResult, ...$args): void { $result = Logical::logicalAnd(...$args); - self::assertEquals($expectedResult, $result); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEquals($expectedResult, $result); + } } public function providerAND() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfTest.php index 571a80e36f..2de7c014f1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testIF($expectedResult, ...$args): void { $result = Logical::statementIf(...$args); - self::assertEquals($expectedResult, $result); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEquals($expectedResult, $result); + } } public function providerIF() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/OrTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/OrTest.php index 021cc97bb4..df36627461 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/OrTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/OrTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testOR($expectedResult, ...$args): void { $result = Logical::logicalOr(...$args); - self::assertEquals($expectedResult, $result); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEquals($expectedResult, $result); + } } public function providerOR() diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AveDevTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AveDevTest.php index 571c06c331..a312d02a1f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AveDevTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AveDevTest.php @@ -21,7 +21,12 @@ protected function setUp(): void public function testAVEDEV($expectedResult, ...$args): void { $result = Statistical::AVEDEV(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-12); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-12); + } } public function providerAVEDEV() diff --git a/tests/PhpSpreadsheetTests/Calculation/FunctionsTest.php b/tests/PhpSpreadsheetTests/Calculation/FunctionsTest.php index dfa01822c0..aaf45e2d62 100644 --- a/tests/PhpSpreadsheetTests/Calculation/FunctionsTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/FunctionsTest.php @@ -168,7 +168,12 @@ public function providerIsError() public function testErrorType($expectedResult, ...$args): void { $result = Functions::errorType(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerErrorType() @@ -264,7 +269,12 @@ public function providerIsNonText() public function testIsEven($expectedResult, ...$args): void { $result = Functions::isEven(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerIsEven() @@ -280,7 +290,12 @@ public function providerIsEven() public function testIsOdd($expectedResult, ...$args): void { $result = Functions::isOdd(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerIsOdd() @@ -312,7 +327,12 @@ public function providerTYPE() public function testN($expectedResult, ...$args): void { $result = Functions::n(...$args); - self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + + if (is_object($expectedResult)) { + self::assertEquals($expectedResult, $result); + } else { + self::assertEqualsWithDelta($expectedResult, $result, 1E-8); + } } public function providerN() diff --git a/tests/PhpSpreadsheetTests/Cell/CellTest.php b/tests/PhpSpreadsheetTests/Cell/CellTest.php index 0d9ce33729..1206421c9e 100644 --- a/tests/PhpSpreadsheetTests/Cell/CellTest.php +++ b/tests/PhpSpreadsheetTests/Cell/CellTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Cell; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; @@ -20,7 +21,12 @@ public function testSetValueExplicit($expected, $value, string $dataType): void $cell = $spreadsheet->getActiveSheet()->getCell('A1'); $cell->setValueExplicit($value, $dataType); - self::assertSame($expected, $cell->getValue()); + if ($expected instanceof ExcelException) { + // We can't use assertSame when comparing objects, unless they're the same instance + self::assertEquals($expected, $cell->getValue()); + } else { + self::assertSame($expected, $cell->getValue()); + } } public function providerSetValueExplicit() diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/StartsWithHashTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/StartsWithHashTest.php index d4fe5b2282..4075d89265 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/StartsWithHashTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/StartsWithHashTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\Reader\Xlsx as Reader; use PhpOffice\PhpSpreadsheet\Settings; @@ -31,9 +32,11 @@ public function testStartWithHash(): void unlink($outputFilename); self::assertSame('#define M', $sheet->getActiveSheet()->getCell('A1')->getValue()); + self::assertSame('s', $sheet->getActiveSheet()->getCell('A1')->getDataType()); self::assertSame('#define M', $sheet->getActiveSheet()->getCell('A2')->getCalculatedValue()); - self::assertSame('f', $sheet->getActiveSheet()->getCell('A3')->getDataType()); - self::assertSame('#NAME?', $sheet->getActiveSheet()->getCell('A3')->getCalculatedValue()); + self::assertSame('f', $sheet->getActiveSheet()->getCell('A2')->getDataType()); + self::assertInstanceOf(ExcelException::class, $sheet->getActiveSheet()->getCell('A3')->getCalculatedValue()); + self::assertSame('#NAME?', $sheet->getActiveSheet()->getCell('A3')->getCalculatedValue()->errorName()); self::assertSame('f', $sheet->getActiveSheet()->getCell('A3')->getDataType()); } diff --git a/tests/data/Calculation/DateTime/DATE.php b/tests/data/Calculation/DateTime/DATE.php index 9acc6716b9..552cc97748 100644 --- a/tests/data/Calculation/DateTime/DATE.php +++ b/tests/data/Calculation/DateTime/DATE.php @@ -1,5 +1,7 @@ [ 6890, // '11th November 1918' @@ -222,15 +224,15 @@ null, 10, null, ], [ - '#NUM!', + ExcelException::NUM(), null, null, 10, ], [ - '#NUM!', + ExcelException::NUM(), -20, null, null, ], [ - '#NUM!', + ExcelException::NUM(), -20, 6, 15, ], 'Excel Maximum Date' => [ @@ -238,7 +240,7 @@ 9999, 12, 31, ], 'Exceeded Excel Maximum Date' => [ - '#NUM!', + ExcelException::NUM(), 10000, 1, 1, ], [ @@ -305,15 +307,15 @@ 2010, 'March', 21, ], [ - '#VALUE!', + ExcelException::VALUE(), 'ABC', 1, 21, ], [ - '#VALUE!', + ExcelException::VALUE(), 2010, 'DEF', 21, ], [ - '#VALUE!', + ExcelException::VALUE(), 2010, 3, 'GHI', ], ]; diff --git a/tests/data/Calculation/DateTime/DATEDIF.php b/tests/data/Calculation/DateTime/DATEDIF.php index a6d2d76122..5e6e780476 100644 --- a/tests/data/Calculation/DateTime/DATEDIF.php +++ b/tests/data/Calculation/DateTime/DATEDIF.php @@ -1,5 +1,7 @@ 0, return NUM', 0.10, [1000.0, 1000.1], ['2018-06-30', '2018-07-30'], ], [ - '#NUM!', + ExcelException::NUM(), 'If maximum value < 0, return NUM', 0.10, [-1000.0, -1000.1], ['2018-06-30', '2018-07-30'], ], [ - '#VALUE!', + ExcelException::VALUE(), 'If any value is non-numeric, return VALUE', 0.10, [-1000.0, 1000.1, 'x'], ['2018-06-30', '2018-07-30', '2018-08-30'], ], [ - '#VALUE!', + ExcelException::VALUE(), 'If first date is non-numeric, return VALUE', 0.10, [-1000.0, 1000.1, 1000.2], ['2018-06x30', '2018-07-30', '2018-08-30'], ], [ - '#VALUE!', + ExcelException::VALUE(), 'If any other date is non-numeric, return VALUE', 0.10, [-1000.0, 1000.1, 1000.2], ['2018-06-30', '2018-07-30', '2018-08z30'], ], [ - '#NUM!', + ExcelException::NUM(), 'If any date is before first date, return NUM', 0.10, [-1000.0, 1000.1, 1000.2], diff --git a/tests/data/Calculation/Functions/ERROR_TYPE.php b/tests/data/Calculation/Functions/ERROR_TYPE.php index b9acafdc8d..c67659d113 100644 --- a/tests/data/Calculation/Functions/ERROR_TYPE.php +++ b/tests/data/Calculation/Functions/ERROR_TYPE.php @@ -1,59 +1,61 @@ [ + ExcelException::NAME(), ], - [ - '#NAME?', + 'Null Value' => [ + ExcelException::NAME(), null, ], - [ + 'Negative Integer' => [ false, -1, ], - [ + 'Zero Value' => [ true, 0, ], - [ + 'Positive Integer' => [ false, 9, ], - [ + 'Odd Float #1' => [ false, 1.25, ], - [ + 'Odd Float #2' => [ false, 1.5, ], - [ + 'Even Float #1' => [ true, 2.25, ], - [ + 'Even Float #2' => [ true, 2.5, ], - [ - '#VALUE!', + 'Empty String' => [ + ExcelException::VALUE(), '', ], - [ + 'String containing Negative Odd Integer' => [ false, '-1', ], - [ + 'String containing Positive Even Integer' => [ true, '2', ], - [ + 'String containing Negative Odd Float' => [ false, '-1.5', ], - [ + 'String containing Positive Even Float' => [ true, '2.5', ], - [ - '#VALUE!', + 'Non-numeric String' => [ + ExcelException::VALUE(), 'ABC', ], - [ - '#VALUE!', - '#VALUE!', + 'VALUE Exception' => [ + ExcelException::VALUE(), + ExcelException::VALUE(), ], - [ - '#VALUE!', - '#N/A', + 'NA Exception' => [ + ExcelException::NA(), + ExcelException::NA(), ], - [ - '#VALUE!', + 'String containing TRUE text' => [ + ExcelException::VALUE(), 'TRUE', ], - [ - '#VALUE!', + 'Boolean True' => [ + ExcelException::VALUE(), true, ], - [ - '#VALUE!', + 'Boolean False' => [ + ExcelException::VALUE(), false, ], ]; diff --git a/tests/data/Calculation/Functions/IS_LOGICAL.php b/tests/data/Calculation/Functions/IS_LOGICAL.php index e38cbf8bff..2fbe70472c 100644 --- a/tests/data/Calculation/Functions/IS_LOGICAL.php +++ b/tests/data/Calculation/Functions/IS_LOGICAL.php @@ -1,5 +1,7 @@ Date: Tue, 4 Aug 2020 10:50:02 +0200 Subject: [PATCH 02/39] phpcs fixes --- src/PhpSpreadsheet/Calculation/DateTime.php | 1 + src/PhpSpreadsheet/Calculation/ExcelException.php | 3 ++- src/PhpSpreadsheet/Calculation/Financial.php | 2 +- src/PhpSpreadsheet/Calculation/Functions.php | 6 ++---- src/PhpSpreadsheet/Calculation/Statistical.php | 1 + src/PhpSpreadsheet/Cell/Cell.php | 1 + src/PhpSpreadsheet/Cell/DataType.php | 2 +- src/PhpSpreadsheet/Shared/Trend/Trend.php | 5 +++++ src/PhpSpreadsheet/Writer/Ods/Content.php | 2 +- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 3 ++- .../PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php | 4 ++-- tests/data/Calculation/ExcelException.php | 2 +- tests/data/Calculation/Financial/PRICEDISC.php | 2 -- tests/data/Calculation/Functions/ERROR_TYPE.php | 2 +- tests/data/Cell/SetValueExplicit.php | 2 +- 15 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index dfd2eff313..7c909d4377 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -72,6 +72,7 @@ public static function getDateValue($dateValue) if ($dateValue instanceof DateTimeInterface) { return Date::PHPToExcel($dateValue); } + return Functions::VALUE(); } diff --git a/src/PhpSpreadsheet/Calculation/ExcelException.php b/src/PhpSpreadsheet/Calculation/ExcelException.php index a96c587ca6..1f5ce4bd4b 100644 --- a/src/PhpSpreadsheet/Calculation/ExcelException.php +++ b/src/PhpSpreadsheet/Calculation/ExcelException.php @@ -54,10 +54,11 @@ public static function fromErrorName(string $value): self } $errorType = self::ERROR_TYPES[$value]; + return $errorType(); } - public static function NULL(): self + public static function null(): self { return new self(self::EXCEL_ERROR_NULL); } diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index be6a6b549e..4f8c278984 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -2333,7 +2333,7 @@ private static function validateXnpv($rate, $values, $dates) return Functions::NAN(); } - foreach($dates as $date) { + foreach ($dates as $date) { $date = DateTime::getDateValue($date); if ($date instanceof ExcelException) { return Functions::VALUE(); diff --git a/src/PhpSpreadsheet/Calculation/Functions.php b/src/PhpSpreadsheet/Calculation/Functions.php index 456bfedbaa..e2a6b543c1 100644 --- a/src/PhpSpreadsheet/Calculation/Functions.php +++ b/src/PhpSpreadsheet/Calculation/Functions.php @@ -2,9 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation; -use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Cell\Cell; -use PhpOffice\PhpSpreadsheet\Reader\Xls\ErrorCode; class Functions { @@ -207,7 +205,7 @@ public static function REF(): ExcelException */ public static function null(): ExcelException { - return ExcelException::NULL(); + return ExcelException::null(); } /** @@ -268,7 +266,7 @@ public static function ifCondition($condition) * * @param mixed $value Value to check * - * @return int|ExcelException + * @return ExcelException|int */ public static function errorType($value = '') { diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 3e0bc806cc..09585d5fb8 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -587,6 +587,7 @@ public static function AVEDEV(...$args) } elseif ($aMean === Functions::VALUE()) { return Functions::VALUE(); } + return $aMean; } diff --git a/src/PhpSpreadsheet/Cell/Cell.php b/src/PhpSpreadsheet/Cell/Cell.php index 63349603f3..5dee411b5f 100644 --- a/src/PhpSpreadsheet/Cell/Cell.php +++ b/src/PhpSpreadsheet/Cell/Cell.php @@ -268,6 +268,7 @@ public function getCalculatedValue($resetLog = true) } elseif (strpos($ex->getMessage(), 'undefined name') !== false) { return \PhpOffice\PhpSpreadsheet\Calculation\Functions::NAME(); } + throw new \PhpOffice\PhpSpreadsheet\Calculation\Exception( $this->getWorksheet()->getTitle() . '!' . $this->getCoordinate() . ' -> ' . $ex->getMessage() ); diff --git a/src/PhpSpreadsheet/Cell/DataType.php b/src/PhpSpreadsheet/Cell/DataType.php index fdee897a2b..244309da6c 100644 --- a/src/PhpSpreadsheet/Cell/DataType.php +++ b/src/PhpSpreadsheet/Cell/DataType.php @@ -65,7 +65,7 @@ public static function checkErrorCode($errorCode): ExcelException } if (!isset(ExcelException::ERROR_CODES[$errorCode])) { - $errorCode = ExcelException::NULL(); + $errorCode = ExcelException::null(); } return $errorCode; diff --git a/src/PhpSpreadsheet/Shared/Trend/Trend.php b/src/PhpSpreadsheet/Shared/Trend/Trend.php index 172428f186..a5a612ca1d 100644 --- a/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -49,6 +49,11 @@ class Trend private static $trendCache = []; /* + * @param mixed $trendType + * @param mixed $yValues + * @param mixed $xValues + * @param mixed $const + * * @return BestFit|false */ public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [], $xValues = [], $const = true) diff --git a/src/PhpSpreadsheet/Writer/Ods/Content.php b/src/PhpSpreadsheet/Writer/Ods/Content.php index 16abd273d6..dab11ac8a6 100644 --- a/src/PhpSpreadsheet/Writer/Ods/Content.php +++ b/src/PhpSpreadsheet/Writer/Ods/Content.php @@ -216,7 +216,7 @@ private function writeCells(XMLWriter $objWriter, Row $row): void $objWriter->writeAttribute('office:value-type', 'string'); } $objWriter->writeAttribute('office:value', $formulaValue); - $objWriter->writeElement('text:p', $formulaValue instanceof ExcelException ? $formulaValue->errorName() :$formulaValue); + $objWriter->writeElement('text:p', $formulaValue instanceof ExcelException ? $formulaValue->errorName() : $formulaValue); break; case DataType::TYPE_INLINE: diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index cb8746ee36..ecfa14fc2a 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -840,7 +840,8 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); } else { // We are really not supposed to reach here - $num = pack('d', 0x00); } + $num = pack('d', 0x00); + } } elseif (is_bool($calculatedValue)) { // Boolean value $num = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF); diff --git a/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php index 76045a175c..a4549a1699 100644 --- a/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php @@ -14,7 +14,7 @@ class ExcelExceptionTest extends TestCase * @param string $name * @param ExcelException $expectedResult */ - public function testFromErrorName($name, $expectedResult) + public function testFromErrorName($name, $expectedResult): void { $result = ExcelException::fromErrorName($name); @@ -26,7 +26,7 @@ public function providerExcelException() return require 'tests/data/Calculation/ExcelException.php'; } - public function testFromInvalidErrorName() + public function testFromInvalidErrorName(): void { self:$this->expectException(SpreadsheetException::class); $result = ExcelException::fromErrorName('#MARK!'); diff --git a/tests/data/Calculation/ExcelException.php b/tests/data/Calculation/ExcelException.php index f8b0c4ce8b..2b61caa883 100644 --- a/tests/data/Calculation/ExcelException.php +++ b/tests/data/Calculation/ExcelException.php @@ -3,7 +3,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; return [ - ['#NULL!', ExcelException::NULL()], + ['#NULL!', ExcelException::null()], ['#DIV/0!', ExcelException::DIV0()], ['#VALUE!', ExcelException::VALUE()], ['#NUM!', ExcelException::NUM()], diff --git a/tests/data/Calculation/Financial/PRICEDISC.php b/tests/data/Calculation/Financial/PRICEDISC.php index 41453a33db..88a0d94e38 100644 --- a/tests/data/Calculation/Financial/PRICEDISC.php +++ b/tests/data/Calculation/Financial/PRICEDISC.php @@ -1,7 +1,5 @@ Date: Tue, 4 Aug 2020 10:56:53 +0200 Subject: [PATCH 03/39] phpcs fixes --- src/PhpSpreadsheet/Reader/Xls/ErrorCode.php | 1 - src/PhpSpreadsheet/Shared/Trend/Trend.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php index 50da530f91..f545f51aad 100644 --- a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php +++ b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php @@ -23,7 +23,6 @@ class ErrorCode * @param int $code * * @return bool|ExcelException - * @throws Exception */ public static function lookup($code) { diff --git a/src/PhpSpreadsheet/Shared/Trend/Trend.php b/src/PhpSpreadsheet/Shared/Trend/Trend.php index a5a612ca1d..a497e2793f 100644 --- a/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -48,7 +48,7 @@ class Trend */ private static $trendCache = []; - /* + /** * @param mixed $trendType * @param mixed $yValues * @param mixed $xValues From 3a9110c3269e99af16077e3a59a9f136d360ca0e Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 11:03:15 +0200 Subject: [PATCH 04/39] And the moral of the story: fixing one phpcs issue can actually create another --- src/PhpSpreadsheet/Reader/Xls/ErrorCode.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php index f545f51aad..7ea773a2c7 100644 --- a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php +++ b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php @@ -3,7 +3,6 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xls; use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; -use PhpOffice\PhpSpreadsheet\Exception; class ErrorCode { From 3d96ebcf4319b10bdada5fc7dfb3efdbe5def0b2 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 13:30:30 +0200 Subject: [PATCH 05/39] This should fix all the scrutinizer issues with the actual code, leaving only its problems with the unit tests... pity it doesn't recognise the validity of previous assertions in a test --- src/PhpSpreadsheet/Calculation/Calculation.php | 8 +------- src/PhpSpreadsheet/Calculation/Functions.php | 14 +++++++------- src/PhpSpreadsheet/Cell/DataType.php | 4 ++-- src/PhpSpreadsheet/Shared/Date.php | 4 ++-- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 12 +++--------- 5 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index f0649f7665..60dfdd516d 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -4796,13 +4796,7 @@ private function validateBinaryOperand(&$operand, &$stack) } // If the string is a numeric value, we treat it as a numeric, so no further testing if (!is_numeric($operand)) { - // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations - if ($operand > '' && $operand[0] == '#') { - $stack->push('Value', $operand); - $this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($operand)); - - return false; - } elseif (!Shared\StringHelper::convertToNumberIfFraction($operand)) { + if (!Shared\StringHelper::convertToNumberIfFraction($operand)) { // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations $stack->push('Error', ExcelException::VALUE()); $this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!')); diff --git a/src/PhpSpreadsheet/Calculation/Functions.php b/src/PhpSpreadsheet/Calculation/Functions.php index e2a6b543c1..0cd8e6f3c4 100644 --- a/src/PhpSpreadsheet/Calculation/Functions.php +++ b/src/PhpSpreadsheet/Calculation/Functions.php @@ -454,14 +454,14 @@ public static function isNonText($value = null) * * @param null|mixed $value The value you want converted * - * @return number N converts values listed in the following table + * @return number|string N converts values listed in the following table * If value is or refers to N returns - * A number That number - * A date The serial number of that date + * A number The number + * A date The serial number of that date * TRUE 1 - * FALSE 0 - * An error value The error value - * Anything else 0 + * FALSE 0 + * An error value The error value (as a string) + * Anything else 0 */ public static function n($value = null) { @@ -479,7 +479,7 @@ public static function n($value = null) case 'object': // Errors if ($value instanceof ExcelException) { - return $value; + return $value->errorName(); } break; diff --git a/src/PhpSpreadsheet/Cell/DataType.php b/src/PhpSpreadsheet/Cell/DataType.php index 244309da6c..b44416d2b2 100644 --- a/src/PhpSpreadsheet/Cell/DataType.php +++ b/src/PhpSpreadsheet/Cell/DataType.php @@ -65,9 +65,9 @@ public static function checkErrorCode($errorCode): ExcelException } if (!isset(ExcelException::ERROR_CODES[$errorCode])) { - $errorCode = ExcelException::null(); + return ExcelException::null(); } - return $errorCode; + return ExcelException::fromErrorName($errorCode); } } diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index d065a7336a..7f75dfa051 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -439,13 +439,13 @@ public static function stringToExcel($dateValue) $dateValueNew = DateTime::DATEVALUE($dateValue); - if ($dateValueNew instanceof ExcelException && $dateValueNew == Functions::VALUE()) { + if ($dateValueNew instanceof ExcelException) { return false; } if (strpos($dateValue, ':') !== false) { $timeValue = DateTime::TIMEVALUE($dateValue); - if ($timeValue instanceof ExcelException && $timeValue == Functions::VALUE()) { + if ($timeValue instanceof ExcelException) { return false; } $dateValueNew += $timeValue; diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index ecfa14fc2a..d42672309d 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -833,15 +833,9 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) if (isset($calculatedValue)) { // Since we can't yet get the data type of the calculated value, // we use best effort to determine data type - if ($calculatedValue instanceof ExcelException) { - $errorCodes = DataType::getErrorCodes(); - if (isset($errorCodes[$calculatedValue->errorName()])) { - // Error value - $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); - } else { - // We are really not supposed to reach here - $num = pack('d', 0x00); - } + if ($calculatedValue instanceof ExcelException && isset(DataType::getErrorCodes()[$calculatedValue->errorName()])) { + // Error value + $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); } elseif (is_bool($calculatedValue)) { // Boolean value $num = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF); From 208fc1ddc9b950858ba6a489ce545154f30241f2 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 17:41:20 +0200 Subject: [PATCH 06/39] Simplify some of our nested ifs --- src/PhpSpreadsheet/Calculation/Calculation.php | 12 +++++------- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 6 +----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 60dfdd516d..9709c1577d 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -4795,14 +4795,12 @@ private function validateBinaryOperand(&$operand, &$stack) $operand = self::unwrapResult($operand); } // If the string is a numeric value, we treat it as a numeric, so no further testing - if (!is_numeric($operand)) { - if (!Shared\StringHelper::convertToNumberIfFraction($operand)) { - // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations - $stack->push('Error', ExcelException::VALUE()); - $this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!')); + if (!is_numeric($operand) && !Shared\StringHelper::convertToNumberIfFraction($operand)) { + // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations + $stack->push('Error', ExcelException::VALUE()); + $this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!')); - return false; - } + return false; } } diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index d42672309d..3dcfde9a63 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -829,6 +829,7 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) // Initialize possible additional value for STRING record that should be written after the FORMULA record? $stringValue = null; + $num = pack('d', 0x00); // calculated value if (isset($calculatedValue)) { // Since we can't yet get the data type of the calculated value, @@ -851,12 +852,7 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) $stringValue = $calculatedValue; $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); } - } else { - // We are really not supposed to reach here - $num = pack('d', 0x00); } - } else { - $num = pack('d', 0x00); } $grbit = 0x03; // Option flags From ecb3c102652c85de2c0fc5a1c86d13a2e2561a6f Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 19:18:07 +0200 Subject: [PATCH 07/39] Refactor of xls writer for formulae --- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 62 +++++++++++---------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index 3dcfde9a63..d5ef0568f1 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -827,33 +827,9 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) { $record = 0x0006; // Record identifier // Initialize possible additional value for STRING record that should be written after the FORMULA record? - $stringValue = null; - - $num = pack('d', 0x00); - // calculated value - if (isset($calculatedValue)) { - // Since we can't yet get the data type of the calculated value, - // we use best effort to determine data type - if ($calculatedValue instanceof ExcelException && isset(DataType::getErrorCodes()[$calculatedValue->errorName()])) { - // Error value - $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); - } elseif (is_bool($calculatedValue)) { - // Boolean value - $num = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF); - } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { - // Numeric value - $num = pack('d', $calculatedValue); - } elseif (is_string($calculatedValue)) { - if ($calculatedValue === '') { - // Empty string (and BIFF8) - $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); - } else { - // Non-empty string value (or empty string BIFF5) - $stringValue = $calculatedValue; - $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); - } - } - } + $stringValue = (is_string($calculatedValue) && $calculatedValue !== '') ? $calculatedValue : null; + + $packedResultValue = (isset($calculatedValue)) ? $this->packCalculatedValue($calculatedValue) : pack('d', 0x00); $grbit = 0x03; // Option flags $unknown = 0x0000; // Must be zero @@ -879,7 +855,7 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) $header = pack('vv', $record, $length); $data = pack('vvv', $row, $col, $xfIndex) - . $num + . $packedResultValue . pack('vVv', $grbit, $unknown, $formlen); $this->append($header . $data . $formula); @@ -894,6 +870,36 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) } } + /** + * @param $calculatedValue + * @return string + */ + private function packCalculatedValue($calculatedValue): string + { + // Since we can't yet get the data type of the calculated value, + // we use best effort to determine data type + if ($calculatedValue instanceof ExcelException && isset(DataType::getErrorCodes()[$calculatedValue->errorName()])) { + // Error value + $packedValue = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); + } elseif (is_bool($calculatedValue)) { + // Boolean value + $packedValue = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); + } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { + // Numeric value + $packedValue = pack('d', $calculatedValue); + } elseif (is_string($calculatedValue)) { + if ($calculatedValue === '') { + // Empty string (and BIFF8) + $packedValue = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + } else { + // Non-empty string value (or empty string BIFF5) + $packedValue = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + } + } + + return $packedValue; + } + /** * Write a STRING record. This. * From 4b95bf4c5e9de7e13090f453b3df456559e75e2f Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 19:38:45 +0200 Subject: [PATCH 08/39] Fix phpcs issue --- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index d5ef0568f1..a355505348 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -883,7 +883,7 @@ private function packCalculatedValue($calculatedValue): string $packedValue = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); } elseif (is_bool($calculatedValue)) { // Boolean value - $packedValue = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); + $packedValue = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF); } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { // Numeric value $packedValue = pack('d', $calculatedValue); From 51037e56dbefc150dd146d7846f6c3e5cdc9c62b Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 19:44:58 +0200 Subject: [PATCH 09/39] Fix phpcs issue --- src/PhpSpreadsheet/Writer/Xls/Worksheet.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index a355505348..cb84bf7040 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -872,7 +872,6 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) /** * @param $calculatedValue - * @return string */ private function packCalculatedValue($calculatedValue): string { From cd0ff30fc86673771c1cbbffa2e98628d1e8b985 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 20:19:14 +0200 Subject: [PATCH 10/39] Fix exception return datatypes in Engineering functions --- .../Calculation/Engineering.php | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Engineering.php b/src/PhpSpreadsheet/Calculation/Engineering.php index 1256dd90be..b1d338d2ae 100644 --- a/src/PhpSpreadsheet/Calculation/Engineering.php +++ b/src/PhpSpreadsheet/Calculation/Engineering.php @@ -1755,7 +1755,7 @@ public static function IMABS($complexNumber) * * @param string $complexNumber the complex number for which you want the argument theta * - * @return float|string + * @return ExcelException|float */ public static function IMARGUMENT($complexNumber) { @@ -1988,7 +1988,7 @@ public static function IMTAN($complexNumber) * * @param string $complexNumber the complex number for which you want the square root * - * @return string + * @return ExcelException|string */ public static function IMSQRT($complexNumber) { @@ -2012,7 +2012,7 @@ public static function IMSQRT($complexNumber) * * @param string $complexNumber the complex number for which you want the natural logarithm * - * @return string + * @return ExcelException|string */ public static function IMLN($complexNumber) { @@ -2036,7 +2036,7 @@ public static function IMLN($complexNumber) * * @param string $complexNumber the complex number for which you want the common logarithm * - * @return string + * @return ExcelException|string */ public static function IMLOG10($complexNumber) { @@ -2060,7 +2060,7 @@ public static function IMLOG10($complexNumber) * * @param string $complexNumber the complex number for which you want the base-2 logarithm * - * @return string + * @return ExcelException|string */ public static function IMLOG2($complexNumber) { @@ -2104,7 +2104,7 @@ public static function IMEXP($complexNumber) * @param string $complexNumber the complex number you want to raise to a power * @param float $realNumber the power to which you want to raise the complex number * - * @return string + * @return ExcelException|string */ public static function IMPOWER($complexNumber, $realNumber) { @@ -2129,7 +2129,7 @@ public static function IMPOWER($complexNumber, $realNumber) * @param string $complexDividend the complex numerator or dividend * @param string $complexDivisor the complex denominator or divisor * - * @return string + * @return ExcelException|string */ public static function IMDIV($complexDividend, $complexDivisor) { @@ -2154,7 +2154,7 @@ public static function IMDIV($complexDividend, $complexDivisor) * @param string $complexNumber1 the complex number from which to subtract complexNumber2 * @param string $complexNumber2 the complex number to subtract from complexNumber1 * - * @return string + * @return ExcelException|string */ public static function IMSUB($complexNumber1, $complexNumber2) { @@ -2178,7 +2178,7 @@ public static function IMSUB($complexNumber1, $complexNumber2) * * @param string ...$complexNumbers Series of complex numbers to add * - * @return string + * @return ExcelException|string */ public static function IMSUM(...$complexNumbers) { @@ -2208,7 +2208,7 @@ public static function IMSUM(...$complexNumbers) * * @param string ...$complexNumbers Series of complex numbers to multiply * - * @return string + * @return ExcelException|string */ public static function IMPRODUCT(...$complexNumbers) { @@ -2344,7 +2344,7 @@ private static function validateBitwiseArgument($value) * @param int $number1 * @param int $number2 * - * @return int|string + * @return ExcelException|int */ public static function BITAND($number1, $number2) { @@ -2369,7 +2369,7 @@ public static function BITAND($number1, $number2) * @param int $number1 * @param int $number2 * - * @return int|string + * @return ExcelException|int */ public static function BITOR($number1, $number2) { @@ -2394,7 +2394,7 @@ public static function BITOR($number1, $number2) * @param int $number1 * @param int $number2 * - * @return int|string + * @return ExcelException|int */ public static function BITXOR($number1, $number2) { @@ -2419,7 +2419,7 @@ public static function BITXOR($number1, $number2) * @param int $number * @param int $shiftAmount * - * @return int|string + * @return ExcelException|int */ public static function BITLSHIFT($number, $shiftAmount) { @@ -2450,7 +2450,7 @@ public static function BITLSHIFT($number, $shiftAmount) * @param int $number * @param int $shiftAmount * - * @return int|string + * @return ExcelException|int */ public static function BITRSHIFT($number, $shiftAmount) { From 5b84ebbc563ef7322bd7b5c5e8ad243af125ac23 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 20:56:18 +0200 Subject: [PATCH 11/39] Fix exception return datatypes in Engineering and Statistical functions --- src/PhpSpreadsheet/Calculation/Database.php | 2 +- .../Calculation/Engineering.php | 16 +- src/PhpSpreadsheet/Calculation/MathTrig.php | 2 +- .../Calculation/Statistical.php | 138 +++++++++--------- 4 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Database.php b/src/PhpSpreadsheet/Calculation/Database.php index 2ba4af2dc4..45cdcb31b6 100644 --- a/src/PhpSpreadsheet/Calculation/Database.php +++ b/src/PhpSpreadsheet/Calculation/Database.php @@ -145,7 +145,7 @@ private static function getFilteredColumn($database, $field, $criteria) * the column label in which you specify a condition for the * column. * - * @return float|string + * @return ExcelException|float */ public static function DAVERAGE($database, $field, $criteria) { diff --git a/src/PhpSpreadsheet/Calculation/Engineering.php b/src/PhpSpreadsheet/Calculation/Engineering.php index b1d338d2ae..00568a9024 100644 --- a/src/PhpSpreadsheet/Calculation/Engineering.php +++ b/src/PhpSpreadsheet/Calculation/Engineering.php @@ -2321,16 +2321,16 @@ private static function validateBitwiseArgument($value) if ($value == (int) ($value)) { $value = (int) ($value); if (($value > 2 ** 48 - 1) || ($value < 0)) { - throw new Exception(Functions::NAN()); + throw new Exception(Functions::NAN()->errorName()); } return $value; } - throw new Exception(Functions::NAN()); + throw new Exception(Functions::NAN()->errorName()); } - throw new Exception(Functions::VALUE()); + throw new Exception(Functions::VALUE()->errorName()); } /** @@ -2352,7 +2352,7 @@ public static function BITAND($number1, $number2) $number1 = self::validateBitwiseArgument($number1); $number2 = self::validateBitwiseArgument($number2); } catch (Exception $e) { - return $e->getMessage(); + return ExcelException::fromErrorName($e->getMessage()); } return $number1 & $number2; @@ -2377,7 +2377,7 @@ public static function BITOR($number1, $number2) $number1 = self::validateBitwiseArgument($number1); $number2 = self::validateBitwiseArgument($number2); } catch (Exception $e) { - return $e->getMessage(); + return ExcelException::fromErrorName($e->getMessage()); } return $number1 | $number2; @@ -2402,7 +2402,7 @@ public static function BITXOR($number1, $number2) $number1 = self::validateBitwiseArgument($number1); $number2 = self::validateBitwiseArgument($number2); } catch (Exception $e) { - return $e->getMessage(); + return ExcelException::fromErrorName($e->getMessage()); } return $number1 ^ $number2; @@ -2426,7 +2426,7 @@ public static function BITLSHIFT($number, $shiftAmount) try { $number = self::validateBitwiseArgument($number); } catch (Exception $e) { - return $e->getMessage(); + return ExcelException::fromErrorName($e->getMessage()); } $shiftAmount = Functions::flattenSingleValue($shiftAmount); @@ -2457,7 +2457,7 @@ public static function BITRSHIFT($number, $shiftAmount) try { $number = self::validateBitwiseArgument($number); } catch (Exception $e) { - return $e->getMessage(); + return ExcelException::fromErrorName($e->getMessage()); } $shiftAmount = Functions::flattenSingleValue($shiftAmount); diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index 7539659ec2..0150e3ecdb 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -1282,7 +1282,7 @@ function ($index) use ($cellReference) { * in hidden rows or columns * @param mixed[] $args A mixed data series of values * - * @return float|string + * @return ExcelException|float */ public static function SUBTOTAL($functionType, ...$args) { diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 09585d5fb8..2e1574602a 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -571,7 +571,7 @@ private static function isAcceptedCountable($arg, $k) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function AVEDEV(...$args) { @@ -627,7 +627,7 @@ public static function AVEDEV(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function AVERAGE(...$args) { @@ -669,7 +669,7 @@ public static function AVERAGE(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function AVERAGEA(...$args) { @@ -714,7 +714,7 @@ public static function AVERAGEA(...$args) * @param string $condition the criteria that defines which cells will be checked * @param mixed[] $averageArgs Data values * - * @return float|string + * @return ExcelException|float */ public static function AVERAGEIF($aArgs, $condition, $averageArgs = []) { @@ -764,7 +764,7 @@ public static function AVERAGEIF($aArgs, $condition, $averageArgs = []) * @param mixed $rMin * @param mixed $rMax * - * @return float|string + * @return ExcelException|float */ public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1) { @@ -803,7 +803,7 @@ public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1) * @param float $rMin Minimum value * @param float $rMax Maximum value * - * @return float|string + * @return ExcelException|float */ public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1) { @@ -861,7 +861,7 @@ public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1 * @param float $probability Probability of success on each trial * @param bool $cumulative * - * @return float|string + * @return ExcelException|float */ public static function BINOMDIST($value, $trials, $probability, $cumulative) { @@ -903,7 +903,7 @@ public static function BINOMDIST($value, $trials, $probability, $cumulative) * @param float $value Value for the function * @param float $degrees degrees of freedom * - * @return float|string + * @return ExcelException|float */ public static function CHIDIST($value, $degrees) { @@ -937,7 +937,7 @@ public static function CHIDIST($value, $degrees) * @param float $probability Probability for the function * @param float $degrees degrees of freedom * - * @return float|string + * @return ExcelException|float */ public static function CHIINV($probability, $degrees) { @@ -998,7 +998,7 @@ public static function CHIINV($probability, $degrees) * @param float $stdDev Standard Deviation * @param float $size * - * @return float|string + * @return ExcelException|float */ public static function CONFIDENCE($alpha, $stdDev, $size) { @@ -1029,7 +1029,7 @@ public static function CONFIDENCE($alpha, $stdDev, $size) * @param mixed $yValues array of mixed Data Series Y * @param null|mixed $xValues array of mixed Data Series X * - * @return float|string + * @return ExcelException|float */ public static function CORREL($yValues, $xValues = null) { @@ -1258,7 +1258,7 @@ public static function COUNTIFS(...$args) * @param mixed $yValues array of mixed Data Series Y * @param mixed $xValues array of mixed Data Series X * - * @return float|string + * @return ExcelException|float */ public static function COVAR($yValues, $xValues) { @@ -1291,7 +1291,7 @@ public static function COVAR($yValues, $xValues) * @param float $probability probability of a success on each trial * @param float $alpha criterion value * - * @return int|string + * @return ExcelException|int * * @TODO Warning. This implementation differs from the algorithm detailed on the MS * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess @@ -1416,7 +1416,7 @@ public static function CRITBINOM($trials, $probability, $alpha) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function DEVSQ(...$args) { @@ -1469,7 +1469,7 @@ public static function DEVSQ(...$args) * @param float $lambda The parameter value * @param bool $cumulative * - * @return float|string + * @return ExcelException|float */ public static function EXPONDIST($value, $lambda, $cumulative) { @@ -1517,7 +1517,7 @@ private static function regularizedIncompleteBeta($value, $a, $b) * @param bool $cumulative If cumulative is TRUE, F.DIST returns the cumulative distribution function; * if FALSE, it returns the probability density function. * - * @return float|string + * @return ExcelException|float */ public static function FDIST2($value, $u, $v, $cumulative) { @@ -1558,7 +1558,7 @@ public static function FDIST2($value, $u, $v, $cumulative) * * @param float $value * - * @return float|string + * @return ExcelException|float */ public static function FISHER($value) { @@ -1584,7 +1584,7 @@ public static function FISHER($value) * * @param float $value * - * @return float|string + * @return ExcelException|float */ public static function FISHERINV($value) { @@ -1606,7 +1606,7 @@ public static function FISHERINV($value) * @param mixed $yValues array of mixed Data Series Y * @param mixed $xValues of mixed Data Series X * - * @return bool|float|string + * @return ExcelException|bool|float */ public static function FORECAST($xValue, $yValues, $xValues) { @@ -1637,7 +1637,7 @@ public static function FORECAST($xValue, $yValues, $xValues) * * @param float $value * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function GAMMAFunction($value) { @@ -1661,7 +1661,7 @@ public static function GAMMAFunction($value) * @param float $b Parameter to the distribution * @param bool $cumulative * - * @return float|string + * @return ExcelException|float */ public static function GAMMADIST($value, $a, $b, $cumulative) { @@ -1694,7 +1694,7 @@ public static function GAMMADIST($value, $a, $b, $cumulative) * @param float $alpha Parameter to the distribution * @param float $beta Parameter to the distribution * - * @return float|string + * @return ExcelException|float */ public static function GAMMAINV($probability, $alpha, $beta) { @@ -1754,7 +1754,7 @@ public static function GAMMAINV($probability, $alpha, $beta) * * @param float $value * - * @return float|string + * @return ExcelException|float */ public static function GAMMALN($value) { @@ -1779,7 +1779,7 @@ public static function GAMMALN($value) * * @param float $value * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function GAUSS($value) { @@ -1803,7 +1803,7 @@ public static function GAUSS($value) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function GEOMEAN(...$args) { @@ -1863,7 +1863,7 @@ public static function GROWTH($yValues, $xValues = [], $newValues = [], $const = * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function HARMEAN(...$args) { @@ -1906,7 +1906,7 @@ public static function HARMEAN(...$args) * @param float $populationSuccesses Number of successes in the population * @param float $populationNumber Population size * - * @return float|string + * @return ExcelException|float */ public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber) { @@ -1947,7 +1947,7 @@ public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationS * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float|string + * @return ExcelException|float */ public static function INTERCEPT($yValues, $xValues) { @@ -1978,7 +1978,7 @@ public static function INTERCEPT($yValues, $xValues) * * @param array ...$args Data Series * - * @return float|string + * @return ExcelException|float */ public static function KURT(...$args) { @@ -2023,7 +2023,7 @@ public static function KURT(...$args) * * @param mixed $args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function LARGE(...$args) { @@ -2065,7 +2065,7 @@ public static function LARGE(...$args) * @param bool $const a logical value specifying whether to force the intersect to equal 0 * @param bool $stats a logical value specifying whether to return additional regression statistics * - * @return array|int|string The result, or a string containing an error + * @return ExcelException|array|int The result, or an ExcelException containing an error */ public static function LINEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -2124,7 +2124,7 @@ public static function LINEST($yValues, $xValues = null, $const = true, $stats = * @param bool $const a logical value specifying whether to force the intersect to equal 0 * @param bool $stats a logical value specifying whether to return additional regression statistics * - * @return array|int|string The result, or a string containing an error + * @return ExcelException|array|int The result, or an ExcelException containing an error */ public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -2187,7 +2187,7 @@ public static function LOGEST($yValues, $xValues = null, $const = true, $stats = * @param float $mean * @param float $stdDev * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error * * @TODO Try implementing P J Acklam's refinement algorithm for greater * accuracy if I can get my head round the mathematics @@ -2220,7 +2220,7 @@ public static function LOGINV($probability, $mean, $stdDev) * @param float $mean * @param float $stdDev * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function LOGNORMDIST($value, $mean, $stdDev) { @@ -2250,7 +2250,7 @@ public static function LOGNORMDIST($value, $mean, $stdDev) * @param float $stdDev * @param bool $cumulative * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function LOGNORMDIST2($value, $mean, $stdDev, $cumulative = false) { @@ -2416,7 +2416,7 @@ public static function MAXIFS(...$args) * * @param mixed ...$args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function MEDIAN(...$args) { @@ -2637,7 +2637,7 @@ private static function modeCalc($data) * * @param mixed ...$args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function MODE(...$args) { @@ -2674,7 +2674,7 @@ public static function MODE(...$args) * @param float $successes Threshold number of Successes * @param float $probability Probability of success on each trial * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function NEGBINOMDIST($failures, $successes, $probability) { @@ -2712,7 +2712,7 @@ public static function NEGBINOMDIST($failures, $successes, $probability) * @param float $stdDev Standard Deviation * @param bool $cumulative * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function NORMDIST($value, $mean, $stdDev, $cumulative) { @@ -2745,7 +2745,7 @@ public static function NORMDIST($value, $mean, $stdDev, $cumulative) * @param float $mean Mean Value * @param float $stdDev Standard Deviation * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function NORMINV($probability, $mean, $stdDev) { @@ -2776,7 +2776,7 @@ public static function NORMINV($probability, $mean, $stdDev) * * @param float $value * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function NORMSDIST($value) { @@ -2798,7 +2798,7 @@ public static function NORMSDIST($value) * @param float $value * @param bool $cumulative * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function NORMSDIST2($value, $cumulative) { @@ -2818,7 +2818,7 @@ public static function NORMSDIST2($value, $cumulative) * * @param float $value * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function NORMSINV($value) { @@ -2835,7 +2835,7 @@ public static function NORMSINV($value) * * @param mixed $args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function PERCENTILE(...$args) { @@ -2860,7 +2860,7 @@ public static function PERCENTILE(...$args) sort($mArgs); $count = self::COUNT($mArgs); $index = $entry * ($count - 1); - $iBase = floor($index); + $iBase = (int) floor($index); if ($index == $iBase) { return $mArgs[$index]; } @@ -2883,7 +2883,7 @@ public static function PERCENTILE(...$args) * @param int $value the number whose rank you want to find * @param int $significance the number of significant digits for the returned percentage value * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function PERCENTRANK($valueSet, $value, $significance = 3) { @@ -2933,7 +2933,7 @@ public static function PERCENTRANK($valueSet, $value, $significance = 3) * @param int $numObjs Number of different objects * @param int $numInSet Number of objects in each permutation * - * @return int|string Number of permutations, or a string containing an error + * @return ExcelException|int Number of permutations, or an ExcelException containing an error */ public static function PERMUT($numObjs, $numInSet) { @@ -2963,7 +2963,7 @@ public static function PERMUT($numObjs, $numInSet) * @param float $mean Mean Value * @param bool $cumulative * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function POISSON($value, $mean, $cumulative) { @@ -3002,7 +3002,7 @@ public static function POISSON($value, $mean, $cumulative) * * @param mixed $args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function QUARTILE(...$args) { @@ -3032,7 +3032,7 @@ public static function QUARTILE(...$args) * @param float[] $valueSet An array of, or a reference to, a list of numbers * @param int $order Order to sort the values in the value set * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function RANK($value, $valueSet, $order = 0) { @@ -3067,7 +3067,7 @@ public static function RANK($value, $valueSet, $order = 0) * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function RSQ($yValues, $xValues) { @@ -3098,7 +3098,7 @@ public static function RSQ($yValues, $xValues) * * @param array ...$args Data Series * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function SKEW(...$args) { @@ -3137,7 +3137,7 @@ public static function SKEW(...$args) * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function SLOPE($yValues, $xValues) { @@ -3169,7 +3169,7 @@ public static function SLOPE($yValues, $xValues) * * @param mixed $args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function SMALL(...$args) { @@ -3210,7 +3210,7 @@ public static function SMALL(...$args) * @param float $mean Mean Value * @param float $stdDev Standard Deviation * - * @return float|string Standardized value, or a string containing an error + * @return ExcelException|float Standardized value, or an ExcelException containing an error */ public static function STANDARDIZE($value, $mean, $stdDev) { @@ -3240,7 +3240,7 @@ public static function STANDARDIZE($value, $mean, $stdDev) * * @param mixed ...$args Data values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function STDEV(...$args) { @@ -3289,7 +3289,7 @@ public static function STDEV(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function STDEVA(...$args) { @@ -3341,7 +3341,7 @@ public static function STDEVA(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function STDEVP(...$args) { @@ -3388,7 +3388,7 @@ public static function STDEVP(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function STDEVPA(...$args) { @@ -3438,7 +3438,7 @@ public static function STDEVPA(...$args) * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float|string + * @return ExcelException|float */ public static function STEYX($yValues, $xValues) { @@ -3468,7 +3468,7 @@ public static function STEYX($yValues, $xValues) * @param float $degrees degrees of freedom * @param float $tails number of tails (1 or 2) * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function TDIST($value, $degrees, $tails) { @@ -3531,7 +3531,7 @@ public static function TDIST($value, $degrees, $tails) * @param float $probability Probability for the function * @param float $degrees degrees of freedom * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function TINV($probability, $degrees) { @@ -3625,7 +3625,7 @@ public static function TREND($yValues, $xValues = [], $newValues = [], $const = * * @param mixed $args Data values * - * @return float|string + * @return ExcelException|float */ public static function TRIMMEAN(...$args) { @@ -3668,7 +3668,7 @@ public static function TRIMMEAN(...$args) * * @param mixed ...$args Data values * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function VARFunc(...$args) { @@ -3710,7 +3710,7 @@ public static function VARFunc(...$args) * * @param mixed ...$args Data values * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function VARA(...$args) { @@ -3765,7 +3765,7 @@ public static function VARA(...$args) * * @param mixed ...$args Data values * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function VARP(...$args) { @@ -3808,7 +3808,7 @@ public static function VARP(...$args) * * @param mixed ...$args Data values * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function VARPA(...$args) { @@ -3864,7 +3864,7 @@ public static function VARPA(...$args) * @param float $beta Beta Parameter * @param bool $cumulative * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function WEIBULL($value, $alpha, $beta, $cumulative) { @@ -3898,7 +3898,7 @@ public static function WEIBULL($value, $alpha, $beta, $cumulative) * @param float $m0 Alpha Parameter * @param float $sigma Beta Parameter * - * @return float|string (string if result is an error) + * @return ExcelException|float (ExcelException if result is an error) */ public static function ZTEST($dataSet, $m0, $sigma = null) { From a9f50a5252f9ae4d7fb97340097791a747f0f496 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 4 Aug 2020 21:04:56 +0200 Subject: [PATCH 12/39] Fix some more phpcs issues --- src/PhpSpreadsheet/Calculation/Statistical.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 2e1574602a..2c2f68ab03 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -1606,7 +1606,7 @@ public static function FISHERINV($value) * @param mixed $yValues array of mixed Data Series Y * @param mixed $xValues of mixed Data Series X * - * @return ExcelException|bool|float + * @return bool|ExcelException|float */ public static function FORECAST($xValue, $yValues, $xValues) { @@ -2065,7 +2065,7 @@ public static function LARGE(...$args) * @param bool $const a logical value specifying whether to force the intersect to equal 0 * @param bool $stats a logical value specifying whether to return additional regression statistics * - * @return ExcelException|array|int The result, or an ExcelException containing an error + * @return array|ExcelException|int The result, or an ExcelException containing an error */ public static function LINEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -2124,7 +2124,7 @@ public static function LINEST($yValues, $xValues = null, $const = true, $stats = * @param bool $const a logical value specifying whether to force the intersect to equal 0 * @param bool $stats a logical value specifying whether to return additional regression statistics * - * @return ExcelException|array|int The result, or an ExcelException containing an error + * @return array|ExcelException|int The result, or an ExcelException containing an error */ public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false) { From 6b40b74492606f85d8cf05b4382dae838eeda93a Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 19:22:24 +0200 Subject: [PATCH 13/39] Minor refactoring of HTML Cell writer to eliminate pass by reference --- .../Calculation/Statistical.php | 2 - src/PhpSpreadsheet/Writer/Html.php | 55 +++++++++++-------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 2c2f68ab03..6e2da6f928 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -584,8 +584,6 @@ public static function AVEDEV(...$args) if ($aMean instanceof ExcelException) { if ($aMean === Functions::DIV0()) { return Functions::NAN(); - } elseif ($aMean === Functions::VALUE()) { - return Functions::VALUE(); } return $aMean; diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php index 60cd64e8c1..d6ed68fcb2 100644 --- a/src/PhpSpreadsheet/Writer/Html.php +++ b/src/PhpSpreadsheet/Writer/Html.php @@ -1282,8 +1282,10 @@ private function generateRowCellCss($pSheet, $cellAddress, $pRow, $colNum) return [$cell, $cssClass, $coordinate]; } - private function generateRowCellDataValueRich($cell, &$cellData): void + private function generateRowCellDataValueRich($cell) { + $cellData = ''; + // Loop through rich text elements $elements = $cell->getValue()->getRichTextElements(); foreach ($elements as $element) { @@ -1313,44 +1315,51 @@ private function generateRowCellDataValueRich($cell, &$cellData): void $cellData .= htmlspecialchars($cellText); } } + + return $cellData; } - private function generateRowCellDataValue($pSheet, $cell, &$cellData): void + private function generateRowCellDataValue($pSheet, $cell) { if ($cell->getValue() instanceof RichText) { - $this->generateRowCellDataValueRich($cell, $cellData); - } else { - $origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue(); - if ($origData instanceof ExcelException) { - $origData = $origData->errorName(); - } - $cellData = NumberFormat::toFormattedString( - $origData, - $pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(), - [$this, 'formatColor'] - ); - if ($cellData === $origData) { - $cellData = htmlspecialchars($cellData); - } - if ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperscript()) { - $cellData = '' . $cellData . ''; - } elseif ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSubscript()) { - $cellData = '' . $cellData . ''; - } + return $this->generateRowCellDataValueRich($cell); + } + + $displayData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue(); + if ($displayData instanceof ExcelException) { + return $displayData->errorName(); } + + $cellData = NumberFormat::toFormattedString( + $displayData, + $pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(), + [$this, 'formatColor'] + ); + + if ($cellData === $displayData) { + $cellData = htmlspecialchars($cellData); + } + + if ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperscript()) { + $cellData = '' . $cellData . ''; + } elseif ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSubscript()) { + $cellData = '' . $cellData . ''; + } + + return $cellData; } private function generateRowCellData($pSheet, $cell, &$cssClass, $cellType) { $cellData = ' '; + if ($cell instanceof Cell) { - $cellData = ''; // Don't know what this does, and no test cases. //if ($cell->getParent() === null) { // $cell->attach($pSheet); //} // Value - $this->generateRowCellDataValue($pSheet, $cell, $cellData); + $cellData = $this->generateRowCellDataValue($pSheet, $cell); // Converts the cell content so that spaces occuring at beginning of each new line are replaced by   // Example: " Hello\n to the world" is converted to "  Hello\n to the world" From 5111ee96394cf241f0823fe0740bdca04b8df1f7 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 19:46:45 +0200 Subject: [PATCH 14/39] Eliminate some redundant code --- src/PhpSpreadsheet/Calculation/DateTime.php | 12 ++++++------ .../Calculation/ExcelExceptionTest.php | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 7c909d4377..5709268c6c 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -1155,7 +1155,7 @@ public static function DAYOFMONTH($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } @@ -1204,7 +1204,7 @@ public static function WEEKDAY($dateValue = 1, $style = 1) } $style = floor($style); - $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { @@ -1322,7 +1322,7 @@ public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY) } $method = self::METHODARR[$method]; - $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { @@ -1362,7 +1362,7 @@ public static function ISOWEEKNUM($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { @@ -1393,7 +1393,7 @@ public static function MONTHOFYEAR($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { @@ -1424,7 +1424,7 @@ public static function YEAR($dateValue = 1) { $dateValue = Functions::flattenSingleValue($dateValue); - $dateValue = ($dateValue === null) ? 1 : $dateValue = self::getDateValue($dateValue); + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { diff --git a/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php index a4549a1699..3bc0f0cada 100644 --- a/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php @@ -28,7 +28,7 @@ public function providerExcelException() public function testFromInvalidErrorName(): void { - self:$this->expectException(SpreadsheetException::class); - $result = ExcelException::fromErrorName('#MARK!'); + $this->expectException(SpreadsheetException::class); + ExcelException::fromErrorName('#MARK!'); } } From 640bce8abc17b692cb1d0a9472a083e936d43c3a Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 20:20:48 +0200 Subject: [PATCH 15/39] Try to let scrutinizer now that we have identified object types in tests --- .../Calculation/Functions/DateTime/EDateTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index a887ba5b63..a37f591a67 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -52,7 +52,9 @@ public function testEDATEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertTrue(is_a($result, 'DateTimeInterface')); - // ... with the correct value + /** ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + * @var \DateTimeInterface $result + */ self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); } } From f8dc0d0c0a440f7e3382cbe436e55817ff594494 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 20:28:15 +0200 Subject: [PATCH 16/39] Ok, let's try and keep phpcs happy with our attempted hackaround for Scrutinizer --- .../Calculation/Functions/DateTime/EDateTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index a37f591a67..85e7d2487c 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -52,7 +52,8 @@ public function testEDATEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertTrue(is_a($result, 'DateTimeInterface')); - /** ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + /** + * ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) * @var \DateTimeInterface $result */ self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); From 2abec34503906fcdd788a88c39da1e1bdaee2815 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 20:37:50 +0200 Subject: [PATCH 17/39] Seriously?!? `/**` is acceptable outside a method, but inside the method only `/*` is allowed?!? --- .../Calculation/Functions/DateTime/EDateTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index 85e7d2487c..ec56c207b2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -52,7 +52,7 @@ public function testEDATEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertTrue(is_a($result, 'DateTimeInterface')); - /** + /* * ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) * @var \DateTimeInterface $result */ From e189a3c665dbd5939d1c7c0e1f753cf9df130091 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 21:10:49 +0200 Subject: [PATCH 18/39] So let's see in Scrutinizer prefers this approach --- .../Calculation/Functions/DateTime/DateTest.php | 4 ++-- .../Calculation/Functions/DateTime/DateValueTest.php | 4 ++-- .../Calculation/Functions/DateTime/EDateTest.php | 9 ++------- .../Calculation/Functions/DateTime/EoMonthTest.php | 4 ++-- .../Calculation/Functions/DateTime/TimeTest.php | 4 ++-- .../Calculation/Functions/DateTime/TimeValueTest.php | 4 ++-- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php index c6af9e4482..c8b9d45681 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php @@ -57,8 +57,8 @@ public function testDATEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertTrue(is_a($result, 'DateTimeInterface')); - // ... with the correct value + self::assertInstanceOf(\DateTimeInterface::class, $result); + // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) self::assertEquals($result->format('d-M-Y'), '31-Jan-2012'); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php index 164122bdc8..9c64bb7945 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php @@ -55,8 +55,8 @@ public function testDATEVALUEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertTrue(is_a($result, DateTimeInterface::class)); - // ... with the correct value + self::assertInstanceOf(\DateTimeInterface::class, $result); + // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) self::assertEquals($result->format('d-M-Y'), '31-Jan-2012'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index ec56c207b2..cf12c23f55 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -48,14 +48,9 @@ public function testEDATEtoDateTimeObject(): void Functions::setReturnDateType(Functions::RETURNDATE_PHP_DATETIME_OBJECT); $result = DateTime::EDATE('2012-1-26', -1); - // Must return an object... - self::assertIsObject($result); // ... of the correct type - self::assertTrue(is_a($result, 'DateTimeInterface')); - /* - * ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) - * @var \DateTimeInterface $result - */ + self::assertInstanceOf(\DateTimeInterface::class, $result); + // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php index f9c54039e1..69ba456573 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php @@ -51,8 +51,8 @@ public function testEOMONTHtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertTrue(is_a($result, 'DateTimeInterface')); - // ... with the correct value + self::assertInstanceOf(\DateTimeInterface::class, $result); + // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) self::assertEquals($result->format('d-M-Y'), '31-Dec-2011'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php index 344061d48b..0d6904c502 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php @@ -48,8 +48,8 @@ public function testTIMEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertTrue(is_a($result, 'DateTimeInterface')); - // ... with the correct value + self::assertInstanceOf(\DateTimeInterface::class, $result); + // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) self::assertEquals($result->format('H:i:s'), '07:30:20'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php index 04b8c05840..cecb42ef7b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php @@ -50,8 +50,8 @@ public function testTIMEVALUEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertTrue(is_a($result, 'DateTimeInterface')); - // ... with the correct value + self::assertInstanceOf(\DateTimeInterface::class, $result); + // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) self::assertEquals($result->format('H:i:s'), '07:30:20'); } } From 01dd73f4c1c6c6017808d3b761094996f1ff8386 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 21:26:04 +0200 Subject: [PATCH 19/39] So let's see in Scrutinizer prefers this approach --- .../Calculation/Functions/DateTime/DateTest.php | 5 +++-- .../Calculation/Functions/DateTime/DateValueTest.php | 4 ++-- .../Calculation/Functions/DateTime/EDateTest.php | 5 +++-- .../Calculation/Functions/DateTime/EoMonthTest.php | 5 +++-- .../Calculation/Functions/DateTime/TimeTest.php | 5 +++-- .../Calculation/Functions/DateTime/TimeValueTest.php | 5 +++-- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php index c8b9d45681..9b58461dd2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use DateTimeInterface; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date; @@ -57,8 +58,8 @@ public function testDATEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertInstanceOf(\DateTimeInterface::class, $result); - // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + self::assertInstanceOf(DateTimeInterface::class, $result); + // ... with the correct value self::assertEquals($result->format('d-M-Y'), '31-Jan-2012'); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php index 9c64bb7945..500bdb01fb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php @@ -55,8 +55,8 @@ public function testDATEVALUEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertInstanceOf(\DateTimeInterface::class, $result); - // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + self::assertInstanceOf(DateTimeInterface::class, $result); + // ... with the correct value self::assertEquals($result->format('d-M-Y'), '31-Jan-2012'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index cf12c23f55..8784f7e306 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use DateTimeInterface; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date; @@ -49,8 +50,8 @@ public function testEDATEtoDateTimeObject(): void $result = DateTime::EDATE('2012-1-26', -1); // ... of the correct type - self::assertInstanceOf(\DateTimeInterface::class, $result); - // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + self::assertInstanceOf(DateTimeInterface::class, $result); + // ... with the correct value self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php index 69ba456573..4ab658f431 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use DateTimeInterface; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date; @@ -51,8 +52,8 @@ public function testEOMONTHtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertInstanceOf(\DateTimeInterface::class, $result); - // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + self::assertInstanceOf(DateTimeInterface::class, $result); + // ... with the correct value self::assertEquals($result->format('d-M-Y'), '31-Dec-2011'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php index 0d6904c502..c96c7597d9 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use DateTimeInterface; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date; @@ -48,8 +49,8 @@ public function testTIMEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertInstanceOf(\DateTimeInterface::class, $result); - // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + self::assertInstanceOf(DateTimeInterface::class, $result); + // ... with the correct value self::assertEquals($result->format('H:i:s'), '07:30:20'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php index cecb42ef7b..386c2fa51e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use DateTimeInterface; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date; @@ -50,8 +51,8 @@ public function testTIMEVALUEtoDateTimeObject(): void // Must return an object... self::assertIsObject($result); // ... of the correct type - self::assertInstanceOf(\DateTimeInterface::class, $result); - // ... with the correct value (using an annotation for what the previous assertion has determined advises Scrutinizer) + self::assertInstanceOf(DateTimeInterface::class, $result); + // ... with the correct value self::assertEquals($result->format('H:i:s'), '07:30:20'); } } From 6b617d9c6105554a2c71cd1c26753942eb076f47 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 21:39:54 +0200 Subject: [PATCH 20/39] For the sake of a space --- .../Calculation/Functions/DateTime/EDateTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index 8784f7e306..c964ba02d0 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -51,7 +51,7 @@ public function testEDATEtoDateTimeObject(): void $result = DateTime::EDATE('2012-1-26', -1); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + // ... with the correct value self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); } } From 7c2c927862365c1fbea0a8599c194e5e400556c8 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 21:55:11 +0200 Subject: [PATCH 21/39] Scrutinizer really is pretty f***ing stupid --- .../Calculation/Functions/DateTime/DateTest.php | 6 +++++- .../Calculation/Functions/DateTime/DateValueTest.php | 6 +++++- .../Calculation/Functions/DateTime/EDateTest.php | 6 +++++- .../Calculation/Functions/DateTime/EoMonthTest.php | 6 +++++- .../Calculation/Functions/DateTime/TimeTest.php | 6 +++++- .../Calculation/Functions/DateTime/TimeValueTest.php | 6 +++++- 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php index 9b58461dd2..2816a6adb1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php @@ -59,7 +59,11 @@ public function testDATEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + /* + * ... with the correct value (using an annotation for what the previous assertion has already determined + * because Scrutinizer simply isn't tha intelligent, and treats that as a major issue) + * @var DateTimeInterface $result + */ self::assertEquals($result->format('d-M-Y'), '31-Jan-2012'); } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php index 500bdb01fb..d2a58b0df2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php @@ -56,7 +56,11 @@ public function testDATEVALUEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + /* + * ... with the correct value (using an annotation for what the previous assertion has already determined + * because Scrutinizer simply isn't tha intelligent, and treats that as a major issue) + * @var DateTimeInterface $result + */ self::assertEquals($result->format('d-M-Y'), '31-Jan-2012'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index c964ba02d0..c7e5a37565 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -51,7 +51,11 @@ public function testEDATEtoDateTimeObject(): void $result = DateTime::EDATE('2012-1-26', -1); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + /* + * ... with the correct value (using an annotation for what the previous assertion has already determined + * because Scrutinizer simply isn't tha intelligent, and treats that as a major issue) + * @var DateTimeInterface $result + */ self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php index 4ab658f431..353fcebdd3 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php @@ -53,7 +53,11 @@ public function testEOMONTHtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + /* + * ... with the correct value (using an annotation for what the previous assertion has already determined + * because Scrutinizer simply isn't tha intelligent, and treats that as a major issue) + * @var DateTimeInterface $result + */ self::assertEquals($result->format('d-M-Y'), '31-Dec-2011'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php index c96c7597d9..904f4953d7 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php @@ -50,7 +50,11 @@ public function testTIMEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + /* + * ... with the correct value (using an annotation for what the previous assertion has already determined + * because Scrutinizer simply isn't tha intelligent, and treats that as a major issue) + * @var DateTimeInterface $result + */ self::assertEquals($result->format('H:i:s'), '07:30:20'); } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php index 386c2fa51e..60e585f3c7 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php @@ -52,7 +52,11 @@ public function testTIMEVALUEtoDateTimeObject(): void self::assertIsObject($result); // ... of the correct type self::assertInstanceOf(DateTimeInterface::class, $result); - // ... with the correct value + /* + * ... with the correct value (using an annotation for what the previous assertion has already determined + * because Scrutinizer simply isn't tha intelligent, and treats that as a major issue) + * @var DateTimeInterface $result + */ self::assertEquals($result->format('H:i:s'), '07:30:20'); } } From 82b4a20adf6ddd70f8a2b00ce3eb668e96e91323 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 23:03:00 +0200 Subject: [PATCH 22/39] Fix some return typehinting for Date and Financial functions --- src/PhpSpreadsheet/Calculation/DateTime.php | 32 ++++++------ src/PhpSpreadsheet/Calculation/Financial.php | 51 ++++++++++---------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 5709268c6c..fc14f3a3bd 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -641,7 +641,7 @@ public static function TIMEVALUE($timeValue) * or a standard date string * @param string $unit * - * @return int|string Interval between the dates + * @return ExcelException|int Interval between the dates */ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') { @@ -684,7 +684,7 @@ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') break; case 'M': - $retVal = (int) 12 * $PHPDiffDateObject->format('%y') + $PHPDiffDateObject->format('%m'); + $retVal = (int) 12 * ((int) $PHPDiffDateObject->format('%y')) + ((int) $PHPDiffDateObject->format('%m')); break; case 'Y': @@ -695,7 +695,7 @@ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') if ($endDays < $startDays) { $retVal = $endDays; $PHPEndDateObject->modify('-' . $endDays . ' days'); - $adjustDays = $PHPEndDateObject->format('j'); + $adjustDays = (int) $PHPEndDateObject->format('j'); $retVal += ($adjustDays - $startDays); } else { $retVal = (int) $PHPDiffDateObject->format('%d'); @@ -751,7 +751,7 @@ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') * @param DateTimeImmutable|float|int|string $startDate Excel date serial value (float), * PHP date timestamp (integer), PHP DateTime object, or a standard date string * - * @return int|string Number of days between start date and end date or an error + * @return ExcelException|int Number of days between start date and end date or an error */ public static function DAYS($endDate = 0, $startDate = 0) { @@ -807,7 +807,7 @@ public static function DAYS($endDate = 0, $startDate = 0) * occur on the 31st of a month become equal to the 30th of the * same month. * - * @return int|string Number of days between start date and end date + * @return ExcelException|int Number of days between start date and end date */ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) { @@ -865,7 +865,7 @@ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) * 3 Actual/365 * 4 European 30/360 * - * @return float|string fraction of the year, or a string containing an error + * @return ExcelException|float fraction of the year, or an ExcelException containing an error */ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { @@ -961,7 +961,7 @@ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string * - * @return int|string Interval between the dates + * @return ExcelException|int Interval between the dates */ public static function NETWORKDAYS($startDate, $endDate, ...$dateArgs) { @@ -1149,7 +1149,7 @@ public static function WORKDAY($startDate, $endDays, ...$dateArgs) * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string * - * @return int|string Day of the month + * @return ExcelException|int Day of the month */ public static function DAYOFMONTH($dateValue = 1) { @@ -1190,7 +1190,7 @@ public static function DAYOFMONTH($dateValue = 1) * 2 Numbers 1 (Monday) through 7 (Sunday). * 3 Numbers 0 (Monday) through 6 (Sunday). * - * @return int|string Day of the week value + * @return ExcelException|int Day of the week value */ public static function WEEKDAY($dateValue = 1, $style = 1) { @@ -1306,7 +1306,7 @@ public static function WEEKDAY($dateValue = 1, $style = 1) * 17 Week begins on Sunday. * 21 ISO (Jan. 4 is week 1, begins on Monday). * - * @return int|string Week Number + * @return ExcelException|int Week Number */ public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY) { @@ -1356,7 +1356,7 @@ public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY) * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string * - * @return int|string Week Number + * @return ExcelException|int Week Number */ public static function ISOWEEKNUM($dateValue = 1) { @@ -1387,7 +1387,7 @@ public static function ISOWEEKNUM($dateValue = 1) * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string * - * @return int|string Month of the year + * @return ExcelException|int Month of the year */ public static function MONTHOFYEAR($dateValue = 1) { @@ -1418,7 +1418,7 @@ public static function MONTHOFYEAR($dateValue = 1) * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string * - * @return int|string Year + * @return ExcelException|int Year */ public static function YEAR($dateValue = 1) { @@ -1449,7 +1449,7 @@ public static function YEAR($dateValue = 1) * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard time string * - * @return int|string Hour + * @return ExcelException|int Hour */ public static function HOUROFDAY($timeValue = 0) { @@ -1490,7 +1490,7 @@ public static function HOUROFDAY($timeValue = 0) * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard time string * - * @return int|string Minute + * @return ExcelException|int Minute */ public static function MINUTE($timeValue = 0) { @@ -1531,7 +1531,7 @@ public static function MINUTE($timeValue = 0) * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard time string * - * @return int|string Second + * @return ExcelException|int Second */ public static function SECOND($timeValue = 0) { diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 4f8c278984..38ccdf6134 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -67,7 +67,7 @@ private static function isValidFrequency($frequency) * 3 365 * 4 European 360 * - * @return int|string Result, or a string containing an error + * @return ExcelException|int Result, or an ExcelException containing an error */ private static function daysPerYear($year, $basis = 0) { @@ -1733,7 +1733,7 @@ public static function PRICEDISC($settlement, $maturity, $discount, $redemption, * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or a string containing an error */ public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis = 0) { @@ -1750,23 +1750,23 @@ public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $ return Functions::NAN(); } $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis); - if (!is_numeric($daysPerYear)) { + if ($daysPerYear instanceof ExcelException) { return $daysPerYear; } $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { + if ($daysBetweenIssueAndSettlement instanceof ExcelException) { // return date error return $daysBetweenIssueAndSettlement; } $daysBetweenIssueAndSettlement *= $daysPerYear; $daysBetweenIssueAndMaturity = DateTime::YEARFRAC($issue, $maturity, $basis); - if (!is_numeric($daysBetweenIssueAndMaturity)) { + if ($daysBetweenIssueAndMaturity instanceof ExcelException) { // return date error return $daysBetweenIssueAndMaturity; } $daysBetweenIssueAndMaturity *= $daysPerYear; $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } @@ -1791,7 +1791,7 @@ public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $ * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or a string containing an error */ public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0) { @@ -1841,7 +1841,7 @@ public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0) * @param float $guess Your guess for what the rate will be. * If you omit guess, it is assumed to be 10 percent. * - * @return float|string + * @return ExcelException|float */ public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { @@ -1906,7 +1906,7 @@ private static function rateNextGuess($rate, $nper, $pmt, $pv, $fv, $type) * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis = 0) { @@ -1942,7 +1942,7 @@ public static function RECEIVED($settlement, $maturity, $investment, $discount, * @param float $pv Present Value * @param float $fv Future Value * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function RRI($nper = 0, $pv = 0, $fv = 0) { @@ -1969,7 +1969,7 @@ public static function RRI($nper = 0, $pv = 0, $fv = 0) * @param mixed $salvage Value at the end of the depreciation * @param mixed $life Number of periods over which the asset is depreciated * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function SLN($cost, $salvage, $life) { @@ -1999,7 +1999,7 @@ public static function SLN($cost, $salvage, $life) * @param mixed $life Number of periods over which the asset is depreciated * @param mixed $period Period * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function SYD($cost, $salvage, $life, $period) { @@ -2031,7 +2031,7 @@ public static function SYD($cost, $salvage, $life, $period) * The maturity date is the date when the Treasury bill expires. * @param int $discount The Treasury bill's discount rate * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function TBILLEQ($settlement, $maturity, $discount) { @@ -2041,11 +2041,12 @@ public static function TBILLEQ($settlement, $maturity, $discount) // Use TBILLPRICE for validation $testValue = self::TBILLPRICE($settlement, $maturity, $discount); - if (is_string($testValue)) { + if ($testValue instanceof ExcelException) { return $testValue; } - if (is_string($maturity = DateTime::getDateValue($maturity))) { + $maturity = DateTime::getDateValue($maturity); + if ($maturity instanceof ExcelException) { return Functions::VALUE(); } @@ -2070,7 +2071,7 @@ public static function TBILLEQ($settlement, $maturity, $discount) * The maturity date is the date when the Treasury bill expires. * @param int $discount The Treasury bill's discount rate * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function TBILLPRICE($settlement, $maturity, $discount) { @@ -2147,7 +2148,7 @@ public static function TBILLYIELD($settlement, $maturity, $price) if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { ++$maturity; $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360; - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } @@ -2395,7 +2396,7 @@ private static function xnpvOrdered($rate, $values, $dates, $ordered = true) * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis = 0) { @@ -2411,11 +2412,11 @@ public static function YIELDDISC($settlement, $maturity, $price, $redemption, $b return Functions::NAN(); } $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis); - if (!is_numeric($daysPerYear)) { + if ($daysPerYear instanceof ExcelException) { return $daysPerYear; } $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } @@ -2446,7 +2447,7 @@ public static function YIELDDISC($settlement, $maturity, $price, $redemption, $b * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis = 0) { @@ -2463,23 +2464,23 @@ public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $ return Functions::NAN(); } $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis); - if (!is_numeric($daysPerYear)) { + if ($daysPerYear instanceof ExcelException) { return $daysPerYear; } $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { + if ($daysBetweenIssueAndSettlement instanceof ExcelException) { // return date error return $daysBetweenIssueAndSettlement; } $daysBetweenIssueAndSettlement *= $daysPerYear; $daysBetweenIssueAndMaturity = DateTime::YEARFRAC($issue, $maturity, $basis); - if (!is_numeric($daysBetweenIssueAndMaturity)) { + if ($daysBetweenIssueAndMaturity instanceof ExcelException) { // return date error return $daysBetweenIssueAndMaturity; } $daysBetweenIssueAndMaturity *= $daysPerYear; $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } From c70ac2fe2b0fb24930a6a673d8ef945e161c87d8 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 23:18:35 +0200 Subject: [PATCH 23/39] Fix some return typehinting for Financial functions --- src/PhpSpreadsheet/Calculation/Financial.php | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 38ccdf6134..6b8f3cfff1 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -154,7 +154,7 @@ public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par return Functions::NAN(); } $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { + if ($daysBetweenIssueAndSettlement instanceof ExcelException) { // return date error return $daysBetweenIssueAndSettlement; } @@ -203,7 +203,7 @@ public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis return Functions::NAN(); } $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { + if ($daysBetweenIssueAndSettlement instanceof ExcelException) { // return date error return $daysBetweenIssueAndSettlement; } @@ -971,7 +971,7 @@ public static function DISC($settlement, $maturity, $price, $redemption, $basis return Functions::NAN(); } $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } @@ -1066,7 +1066,7 @@ public static function DOLLARFR($decimal_dollar = null, $fraction = 0) * @param float $nominal_rate Nominal interest rate * @param int $npery Number of compounding payments per year * - * @return float|string + * @return ExcelException|float */ public static function EFFECT($nominal_rate = 0, $npery = 0) { @@ -1100,7 +1100,7 @@ public static function EFFECT($nominal_rate = 0, $npery = 0) * 0 or omitted At the end of the period. * 1 At the beginning of the period. * - * @return float|string + * @return ExcelException|float */ public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0) { @@ -1170,7 +1170,7 @@ public static function FVSCHEDULE($principal, $schedule) * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return ExcelException|float */ public static function INTRATE($settlement, $maturity, $investment, $redemption, $basis = 0) { @@ -1189,7 +1189,7 @@ public static function INTRATE($settlement, $maturity, $investment, $redemption, return Functions::NAN(); } $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } @@ -1215,7 +1215,7 @@ public static function INTRATE($settlement, $maturity, $investment, $redemption, * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float|string + * @return ExcelException|float */ public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { @@ -1258,7 +1258,7 @@ public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) * calculate the internal rate of return. * @param float $guess A number that you guess is close to the result of IRR * - * @return float|string + * @return ExcelException|float */ public static function IRR($values, $guess = 0.1) { @@ -1368,7 +1368,7 @@ public static function ISPMT(...$args) * @param float $finance_rate The interest rate you pay on the money used in the cash flows * @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function MIRR($values, $finance_rate, $reinvestment_rate) { @@ -1410,7 +1410,7 @@ public static function MIRR($values, $finance_rate, $reinvestment_rate) * @param float $effect_rate Effective interest rate * @param int $npery Number of compounding payments per year * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function NOMINAL($effect_rate = 0, $npery = 0) { @@ -1437,7 +1437,7 @@ public static function NOMINAL($effect_rate = 0, $npery = 0) * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0) { @@ -1505,7 +1505,7 @@ public static function NPV(...$args) * @param float $pv Present Value * @param float $fv Future Value * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function PDURATION($rate = 0, $pv = 0, $fv = 0) { @@ -1534,7 +1534,7 @@ public static function PDURATION($rate = 0, $pv = 0, $fv = 0) * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) { @@ -1569,7 +1569,7 @@ public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { @@ -1687,7 +1687,7 @@ public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis = 0) { @@ -1703,7 +1703,7 @@ public static function PRICEDISC($settlement, $maturity, $discount, $redemption, return Functions::NAN(); } $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } @@ -1922,7 +1922,7 @@ public static function RECEIVED($settlement, $maturity, $investment, $discount, return Functions::NAN(); } $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } From 557277a026a6b42d4bc31a3b57cf2af90c2d1d94 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 5 Aug 2020 23:43:10 +0200 Subject: [PATCH 24/39] Fix some return type docblocks for DateTime and Financial functions --- src/PhpSpreadsheet/Calculation/DateTime.php | 2 +- src/PhpSpreadsheet/Calculation/Financial.php | 53 ++++++++++---------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index fc14f3a3bd..9c53c9113a 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -865,7 +865,7 @@ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) * 3 Actual/365 * 4 European 30/360 * - * @return ExcelException|float fraction of the year, or an ExcelException containing an error + * @return ExcelException|float Fraction of the year, or an ExcelException containing an error */ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 6b8f3cfff1..533f959eeb 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -134,9 +134,9 @@ private static function interestAndPrincipal($rate = 0, $per = 0, $nper = 0, $pv * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000, $frequency = 1, $basis = 0) + public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000.0, $frequency = 1, $basis = 0) { $issue = Functions::flattenSingleValue($issue); $firstinterest = Functions::flattenSingleValue($firstinterest); @@ -185,9 +185,9 @@ public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par * 3 Actual/365 * 4 European 30/360 * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis = 0) + public static function ACCRINTM($issue, $settlement, $rate, $par = 1000.0, $basis = 0) { $issue = Functions::flattenSingleValue($issue); $settlement = Functions::flattenSingleValue($settlement); @@ -379,7 +379,7 @@ public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $peri * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return ExcelException|float */ public static function COUPDAYBS($settlement, $maturity, $frequency, $basis = 0) { @@ -440,7 +440,7 @@ public static function COUPDAYBS($settlement, $maturity, $frequency, $basis = 0) * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return ExcelException|float */ public static function COUPDAYS($settlement, $maturity, $frequency, $basis = 0) { @@ -512,7 +512,7 @@ public static function COUPDAYS($settlement, $maturity, $frequency, $basis = 0) * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return ExcelException|float */ public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis = 0) { @@ -625,7 +625,7 @@ public static function COUPNCD($settlement, $maturity, $frequency, $basis = 0) * 3 Actual/365 * 4 European 30/360 * - * @return int|string + * @return ExcelException|int */ public static function COUPNUM($settlement, $maturity, $frequency, $basis = 0) { @@ -729,7 +729,7 @@ public static function COUPPCD($settlement, $maturity, $frequency, $basis = 0) * 0 or omitted At the end of the period. * 1 At the beginning of the period. * - * @return float|string + * @return ExcelException|float */ public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0) { @@ -775,7 +775,7 @@ public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0) * 0 or omitted At the end of the period. * 1 At the beginning of the period. * - * @return float|string + * @return ExcelException|float */ public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0) { @@ -826,7 +826,7 @@ public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0) * @param int $month Number of months in the first year. If month is omitted, * it defaults to 12. * - * @return float|string + * @return ExcelException|float */ public static function DB($cost, $salvage, $life, $period, $month = 12) { @@ -892,7 +892,7 @@ public static function DB($cost, $salvage, $life, $period, $month = 12) * If factor is omitted, it is assumed to be 2 (the * double-declining balance method). * - * @return float|string + * @return ExcelException|float */ public static function DDB($cost, $salvage, $life, $period, $factor = 2.0) { @@ -952,7 +952,7 @@ public static function DDB($cost, $salvage, $life, $period, $factor = 2.0) * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return ExcelException|float */ public static function DISC($settlement, $maturity, $price, $redemption, $basis = 0) { @@ -995,7 +995,7 @@ public static function DISC($settlement, $maturity, $price, $redemption, $basis * @param float $fractional_dollar Fractional Dollar * @param int $fraction Fraction * - * @return float|string + * @return ExcelException|float */ public static function DOLLARDE($fractional_dollar = null, $fraction = 0) { @@ -1031,7 +1031,7 @@ public static function DOLLARDE($fractional_dollar = null, $fraction = 0) * @param float $decimal_dollar Decimal Dollar * @param int $fraction Fraction * - * @return float|string + * @return ExcelException|float */ public static function DOLLARFR($decimal_dollar = null, $fraction = 0) { @@ -1068,7 +1068,7 @@ public static function DOLLARFR($decimal_dollar = null, $fraction = 0) * * @return ExcelException|float */ - public static function EFFECT($nominal_rate = 0, $npery = 0) + public static function EFFECT($nominal_rate = 0.0, $npery = 0) { $nominal_rate = Functions::flattenSingleValue($nominal_rate); $npery = (int) Functions::flattenSingleValue($npery); @@ -1102,7 +1102,7 @@ public static function EFFECT($nominal_rate = 0, $npery = 0) * * @return ExcelException|float */ - public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0) + public static function FV($rate = 0, $nper = 0, $pmt = 0.0, $pv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $nper = Functions::flattenSingleValue($nper); @@ -1217,7 +1217,7 @@ public static function INTRATE($settlement, $maturity, $investment, $redemption, * * @return ExcelException|float */ - public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) + public static function IPMT($rate, $per, $nper, $pv, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $per = (int) Functions::flattenSingleValue($per); @@ -1412,7 +1412,7 @@ public static function MIRR($values, $finance_rate, $reinvestment_rate) * * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function NOMINAL($effect_rate = 0, $npery = 0) + public static function NOMINAL($effect_rate = 0.0, $npery = 0) { $effect_rate = Functions::flattenSingleValue($effect_rate); $npery = (int) Functions::flattenSingleValue($npery); @@ -1439,7 +1439,7 @@ public static function NOMINAL($effect_rate = 0, $npery = 0) * * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0) + public static function NPER($rate = 0.0, $pmt = 0, $pv = 0.0, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $pmt = Functions::flattenSingleValue($pmt); @@ -1507,7 +1507,7 @@ public static function NPV(...$args) * * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function PDURATION($rate = 0, $pv = 0, $fv = 0) + public static function PDURATION($rate = 0.0, $pv = 0.0, $fv = 0.0) { $rate = Functions::flattenSingleValue($rate); $pv = Functions::flattenSingleValue($pv); @@ -1536,7 +1536,7 @@ public static function PDURATION($rate = 0, $pv = 0, $fv = 0) * * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) + public static function PMT($rate = 0.0, $nper = 0, $pv = 0.0, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $nper = Functions::flattenSingleValue($nper); @@ -1571,7 +1571,7 @@ public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) * * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) + public static function PPMT($rate, $per, $nper, $pv, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $per = (int) Functions::flattenSingleValue($per); @@ -1793,7 +1793,7 @@ public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $ * * @return ExcelException|float Result, or a string containing an error */ - public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0) + public static function PV($rate = 0.0, $nper = 0, $pmt = 0.0, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $nper = Functions::flattenSingleValue($nper); @@ -1944,7 +1944,7 @@ public static function RECEIVED($settlement, $maturity, $investment, $discount, * * @return ExcelException|float Result, or an ExcelException containing an error */ - public static function RRI($nper = 0, $pv = 0, $fv = 0) + public static function RRI($nper = 0.0, $pv = 0.0, $fv = 0.0) { $nper = Functions::flattenSingleValue($nper); $pv = Functions::flattenSingleValue($pv); @@ -2147,11 +2147,12 @@ public static function TBILLYIELD($settlement, $maturity, $price) if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { ++$maturity; - $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360; + $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity); if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } + $daysBetweenSettlementAndMaturity *= 360; } else { $daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement)); } From cc8a6d44fd2040d452025197be8e30a79a52f976 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 6 Aug 2020 21:53:26 +0200 Subject: [PATCH 25/39] Excel error returns in unit tests are now ExcelException rather than string --- src/PhpSpreadsheet/Calculation/DateTime.php | 2 +- tests/data/Calculation/DateTime/DAYS.php | 6 ++- tests/data/Calculation/DateTime/DAYS360.php | 10 +++-- tests/data/Calculation/DateTime/EDATE.php | 6 ++- tests/data/Calculation/DateTime/EOMONTH.php | 6 ++- tests/data/Calculation/DateTime/HOUR.php | 6 ++- .../data/Calculation/DateTime/ISOWEEKNUM.php | 4 +- tests/data/Calculation/DateTime/MINUTE.php | 6 ++- tests/data/Calculation/DateTime/MONTH.php | 6 ++- tests/data/Calculation/DateTime/SECOND.php | 6 ++- tests/data/Calculation/DateTime/TIME.php | 8 ++-- tests/data/Calculation/DateTime/TIMEVALUE.php | 6 ++- tests/data/Calculation/DateTime/WEEKDAY.php | 10 +++-- tests/data/Calculation/DateTime/WEEKNUM.php | 22 +++++----- tests/data/Calculation/DateTime/WORKDAY.php | 4 +- .../data/Calculation/Engineering/BESSELK.php | 24 ++++++----- tests/data/Calculation/Logical/NOT.php | 18 ++++---- tests/data/Calculation/LookupRef/MATCH.php | 22 +++++----- tests/data/Calculation/MathTrig/ACOTH.php | 10 +++-- tests/data/Calculation/MathTrig/COMBIN.php | 14 ++++--- tests/data/Calculation/MathTrig/EVEN.php | 4 +- .../data/Calculation/MathTrig/FACTDOUBLE.php | 6 ++- tests/data/Calculation/MathTrig/LCM.php | 6 ++- tests/data/Calculation/MathTrig/LOG.php | 42 ++++++++++--------- tests/data/Calculation/MathTrig/MOD.php | 4 +- tests/data/Calculation/MathTrig/POWER.php | 36 ++++++++-------- .../data/Calculation/TextData/NUMBERVALUE.php | 12 +++--- 27 files changed, 179 insertions(+), 127 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 9c53c9113a..8869569cf4 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -63,7 +63,7 @@ private static function dateDiff360($startDay, $startMonth, $startYear, $endDay, * * @param mixed $dateValue * - * @return mixed Excel date/time serial value, or ExcelException if error + * @return ExcelException|float Excel date/time serial value, or ExcelException if error */ public static function getDateValue($dateValue) { diff --git a/tests/data/Calculation/DateTime/DAYS.php b/tests/data/Calculation/DateTime/DAYS.php index 26fd4042d0..6f4c14005c 100644 --- a/tests/data/Calculation/DateTime/DAYS.php +++ b/tests/data/Calculation/DateTime/DAYS.php @@ -1,12 +1,14 @@ Date: Fri, 7 Aug 2020 13:42:07 +0200 Subject: [PATCH 26/39] Minor changes to typehinting, and a shortcut for date conversion --- src/PhpSpreadsheet/Calculation/DateTime.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 8869569cf4..be78316878 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -70,7 +70,7 @@ public static function getDateValue($dateValue) if (!is_numeric($dateValue)) { if (is_object($dateValue)) { if ($dateValue instanceof DateTimeInterface) { - return Date::PHPToExcel($dateValue); + return Date::dateTimeToExcel($dateValue); } return Functions::VALUE(); @@ -90,7 +90,7 @@ public static function getDateValue($dateValue) * * @param string $timeValue * - * @return mixed Excel date/time serial value, or string if error + * @return ExcelException|float Excel date/time serial value, or ExcelException if an error */ private static function getTimeValue($timeValue) { @@ -461,8 +461,10 @@ public static function TIME($hour = 0, $minute = 0, $second = 0) * from January 1, 1904, to December 31, 9999. DATEVALUE returns the * #VALUE! error value if date_text is out of this range. * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag + * @return DateTimeInterface|ExcelException|float|int + * Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + * or an ExcelException if the value cannot be converted */ public static function DATEVALUE($dateValue = 1) { @@ -590,8 +592,10 @@ public static function DATEVALUE($dateValue = 1) * within quotation marks that represent time. * Date information in time_text is ignored. * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag + * @return DateTimeInterface|ExcelException|float|int + * Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + * or an ExcelException if the value cannot be converted */ public static function TIMEVALUE($timeValue) { From 86902ff1dd6058c93c3ab06a8327ea295ad551e4 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 7 Aug 2020 17:20:43 +0200 Subject: [PATCH 27/39] Minor tweaks to return datatype docblocks --- src/PhpSpreadsheet/Calculation/DateTime.php | 6 ++++-- src/PhpSpreadsheet/Calculation/Financial.php | 6 ++++-- src/PhpSpreadsheet/Shared/Date.php | 12 ++++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index be78316878..9afac3d0eb 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -811,7 +811,8 @@ public static function DAYS($endDate = 0, $startDate = 0) * occur on the 31st of a month become equal to the 30th of the * same month. * - * @return ExcelException|int Number of days between start date and end date + * @return ExcelException|int + * Number of whoe days between start date and end date, based on the mode used */ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) { @@ -869,7 +870,8 @@ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) * 3 Actual/365 * 4 European 30/360 * - * @return ExcelException|float Fraction of the year, or an ExcelException containing an error + * @return ExcelException|float + * Fraction of the year, or an ExcelException containing an error */ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 533f959eeb..49562dc5ab 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -134,7 +134,8 @@ private static function interestAndPrincipal($rate = 0, $per = 0, $nper = 0, $pv * 3 Actual/365 * 4 European 30/360 * - * @return ExcelException|float Result, or an ExcelException containing an error + * @return ExcelException|float + * Result, or an ExcelException containing an error */ public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000.0, $frequency = 1, $basis = 0) { @@ -185,7 +186,8 @@ public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par * 3 Actual/365 * 4 European 30/360 * - * @return ExcelException|float Result, or an ExcelException containing an error + * @return ExcelException|float + * The result, or an ExcelException containing an error */ public static function ACCRINTM($issue, $settlement, $rate, $par = 1000.0, $basis = 0) { diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 7f75dfa051..78e012c5e3 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -155,7 +155,8 @@ private static function validateTimeZone($timeZone) * if you don't want to treat it as a UTC value * Use the default (UST) unless you absolutely need a conversion * - * @return \DateTime PHP date/time object + * @return DateTimeInterface + * PHP date/time object */ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) { @@ -202,7 +203,8 @@ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) * if you don't want to treat it as a UTC value * Use the default (UST) unless you absolutely need a conversion * - * @return int Unix timetamp for this date/time + * @return int + * Unix timetamp for this date/time */ public static function excelToTimestamp($excelTimestamp, $timeZone = null) { @@ -236,7 +238,8 @@ public static function PHPToExcel($dateValue) * * @param DateTimeInterface $dateValue PHP DateTime object * - * @return float MS Excel serialized date/time value + * @return float + * MS Excel serialized date/time value */ public static function dateTimeToExcel(DateTimeInterface $dateValue) { @@ -276,7 +279,8 @@ public static function timestampToExcel($dateValue) * @param int $minutes * @param int $seconds * - * @return float Excel date/time value + * @return float + * Excel serialized date/time value */ public static function formattedPHPToExcel($year, $month, $day, $hours = 0, $minutes = 0, $seconds = 0) { From c73079fceeaa873b97c6cee185e263c1bdff70ed Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 7 Aug 2020 18:08:42 +0200 Subject: [PATCH 28/39] Minor tweaks to return datatype docblocks --- src/PhpSpreadsheet/Shared/Date.php | 67 +++++++++++++++++++----------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 78e012c5e3..543bc9bab9 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -9,6 +9,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; +use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; class Date @@ -99,7 +100,8 @@ public static function getExcelCalendar() * * @param DateTimeZone|string $timeZone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions * - * @return bool Success or failure + * @return bool + * Success or failure */ public static function setDefaultTimezone($timeZone) { @@ -117,7 +119,8 @@ public static function setDefaultTimezone($timeZone) /** * Return the Default timezone being used for dates. * - * @return DateTimeZone The timezone being used as default for Excel timestamp to PHP DateTime object + * @return DateTimeZone + * The currently timezone being used as default for Excel timestamp to PHP DateTime object */ public static function getDefaultTimezone() { @@ -133,7 +136,10 @@ public static function getDefaultTimezone() * * @param DateTimeZone|string $timeZone The timezone to validate, either as a timezone string or object * - * @return DateTimeZone The timezone as a timezone object + * @return DateTimeZone + * The timezone as a timezone object + * + * @throws PhpSpreadsheetException */ private static function validateTimeZone($timeZone) { @@ -157,25 +163,31 @@ private static function validateTimeZone($timeZone) * * @return DateTimeInterface * PHP date/time object + * + * @throws PhpSpreadsheetException */ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) { - $timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone); - if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) { - if ($excelTimestamp < 1.0) { - // Unix timestamp base date - $baseDate = new \DateTime('1970-01-01', $timeZone); - } else { - // MS Excel calendar base dates - if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) { - // Allow adjustment for 1900 Leap Year in MS Excel - $baseDate = ($excelTimestamp < 60) ? new \DateTime('1899-12-31', $timeZone) : new \DateTime('1899-12-30', $timeZone); + try { + $timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone); + if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) { + if ($excelTimestamp < 1.0) { + // Unix timestamp base date + $baseDate = new \DateTime('1970-01-01', $timeZone); } else { - $baseDate = new \DateTime('1904-01-01', $timeZone); + // MS Excel calendar base dates + if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) { + // Allow adjustment for 1900 Leap Year in MS Excel + $baseDate = ($excelTimestamp < 60) ? new \DateTime('1899-12-31', $timeZone) : new \DateTime('1899-12-30', $timeZone); + } else { + $baseDate = new \DateTime('1904-01-01', $timeZone); + } } + } else { + $baseDate = new \DateTime('1899-12-30', $timeZone); } - } else { - $baseDate = new \DateTime('1899-12-30', $timeZone); + } catch (\Exception $e) { + throw new PhpSpreadsheetException($e->getMessage()); } $days = floor($excelTimestamp); @@ -205,6 +217,8 @@ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) * * @return int * Unix timetamp for this date/time + * + * @throws PhpSpreadsheetException */ public static function excelToTimestamp($excelTimestamp, $timeZone = null) { @@ -217,8 +231,8 @@ public static function excelToTimestamp($excelTimestamp, $timeZone = null) * * @param mixed $dateValue Unix Timestamp or PHP DateTime object or a string * - * @return bool|float Excel date/time value - * or boolean FALSE on failure + * @return bool|float + * Excel date/time value or boolean FALSE on failure */ public static function PHPToExcel($dateValue) { @@ -430,7 +444,8 @@ public static function isDateTimeFormatCode($pFormatCode) * * @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10' * - * @return false|float Excel date/time serial value + * @return false|float + * Excel date/time serial value */ public static function stringToExcel($dateValue) { @@ -459,11 +474,12 @@ public static function stringToExcel($dateValue) } /** - * Converts a month name (either a long or a short name) to a month number. + * Converts a month name (either a long or a short English language name) to a month number. * - * @param string $month Month name or abbreviation + * @param string $month English language Month name or abbreviation * - * @return int|string Month number (1 - 12), or the original string argument if it isn't a valid month name + * @return int|string + * Month number (1 - 12), or the original string argument if it isn't a valid month name */ public static function monthStringToNumber($month) { @@ -479,11 +495,12 @@ public static function monthStringToNumber($month) } /** - * Strips an ordinal from a numeric value. + * Strips an English language ordinal from a numeric value. * - * @param string $day Day number with an ordinal + * @param string $day Day number with or without an English language ordinal * - * @return int|string The integer value with any ordinal stripped, or the original string argument if it isn't a valid numeric + * @return int|string + * The integer value with any ordinal stripped, or the original string argument if it isn't a valid numeric */ public static function dayStringToNumber($day) { From 6cfd4ec1373ad529655bff13e41d9ca5a20a61f3 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 7 Aug 2020 18:21:19 +0200 Subject: [PATCH 29/39] Trying to find that nice balance line between PHPStorm complaining that I'm not handling a thrown exception, and phpcs complaining that I have a @throws annotation in the docblock --- src/PhpSpreadsheet/Shared/Date.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 543bc9bab9..52ec00a669 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -9,7 +9,6 @@ use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; -use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; class Date @@ -138,8 +137,6 @@ public static function getDefaultTimezone() * * @return DateTimeZone * The timezone as a timezone object - * - * @throws PhpSpreadsheetException */ private static function validateTimeZone($timeZone) { @@ -163,8 +160,6 @@ private static function validateTimeZone($timeZone) * * @return DateTimeInterface * PHP date/time object - * - * @throws PhpSpreadsheetException */ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) { From 8c0f96503887e85d653f30846b298237bcfd221e Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 7 Aug 2020 18:44:35 +0200 Subject: [PATCH 30/39] Trying to find that nice balance line between PHPStorm complaining that I'm not handling a thrown exception, and phpcs complaining that I have a @throws annotation in the docblock --- src/PhpSpreadsheet/Calculation/DateTime.php | 20 +++++++++++++------- src/PhpSpreadsheet/Shared/Date.php | 5 ++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 9afac3d0eb..bd17959f35 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -14,7 +14,8 @@ class DateTime * * @param int|string $year The year to test * - * @return bool TRUE if the year is a leap year, otherwise FALSE + * @return bool + * TRUE if the year is a leap year, otherwise FALSE */ public static function isLeapYear($year) { @@ -32,7 +33,8 @@ public static function isLeapYear($year) * @param int $endYear Year of the start date * @param bool $methodUS Whether to use the US method or the European method of calculation * - * @return int Number of days between the start date and the end date + * @return int + * Number of days between the start date and the end date */ private static function dateDiff360($startDay, $startMonth, $startYear, $endDay, $endMonth, $endYear, $methodUS) { @@ -63,7 +65,8 @@ private static function dateDiff360($startDay, $startMonth, $startYear, $endDay, * * @param mixed $dateValue * - * @return ExcelException|float Excel date/time serial value, or ExcelException if error + * @return ExcelException|float + * Excel date/time serial value, or ExcelException if error */ public static function getDateValue($dateValue) { @@ -90,7 +93,8 @@ public static function getDateValue($dateValue) * * @param string $timeValue * - * @return ExcelException|float Excel date/time serial value, or ExcelException if an error + * @return ExcelException|float + * Excel date/time serial value, or ExcelException if an error */ private static function getTimeValue($timeValue) { @@ -143,8 +147,9 @@ private static function adjustDateByMonths($dateValue = 0, $adjustmentMonths = 0 * Excel Function: * NOW() * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag + * @return mixed + * Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag */ public static function DATETIMENOW() { @@ -755,7 +760,8 @@ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') * @param DateTimeImmutable|float|int|string $startDate Excel date serial value (float), * PHP date timestamp (integer), PHP DateTime object, or a standard date string * - * @return ExcelException|int Number of days between start date and end date or an error + * @return ExcelException|int + * Number of days between start date and end date or an error */ public static function DAYS($endDate = 0, $startDate = 0) { diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 52ec00a669..45924bb7ef 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -4,6 +4,7 @@ use DateTimeInterface; use DateTimeZone; +use Exception; use PhpOffice\PhpSpreadsheet\Calculation\DateTime; use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; use PhpOffice\PhpSpreadsheet\Calculation\Functions; @@ -181,7 +182,7 @@ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) } else { $baseDate = new \DateTime('1899-12-30', $timeZone); } - } catch (\Exception $e) { + } catch (Exception $e) { throw new PhpSpreadsheetException($e->getMessage()); } @@ -212,8 +213,6 @@ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) * * @return int * Unix timetamp for this date/time - * - * @throws PhpSpreadsheetException */ public static function excelToTimestamp($excelTimestamp, $timeZone = null) { From 80480bfb056ec7188a9ee87141eef200d2aa9dd9 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 7 Aug 2020 20:24:13 +0200 Subject: [PATCH 31/39] So lets see what this achieves --- src/PhpSpreadsheet/Shared/Date.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 45924bb7ef..ffbe74e353 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -199,8 +199,13 @@ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) } $interval = $days . ' days'; - return $baseDate->modify($interval) + $returnDate = $baseDate->modify($interval) ->setTime((int) $hours, (int) $minutes, (int) $seconds); + if ($returnDate === false) { + throw new PhpSpreadsheetException('Error converting Excel date to DateTime object'); + } + + return $returnDate; } /** From 5f31aaa0fa234eb62d3c1491a896b03e345d97e9 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Mon, 10 Aug 2020 21:45:27 +0200 Subject: [PATCH 32/39] Extra typehinting --- .../Calculation/Functions/DateTime/DateTest.php | 6 +++--- .../Calculation/Functions/DateTime/DateValueTest.php | 2 +- .../Calculation/Functions/DateTime/DayTest.php | 2 +- .../Calculation/Functions/DateTime/Days360Test.php | 6 +++--- .../Calculation/Functions/DateTime/DaysTest.php | 4 ++-- .../Calculation/Functions/DateTime/EDateTest.php | 4 ++-- .../Calculation/Functions/DateTime/EoMonthTest.php | 4 ++-- .../Calculation/Functions/DateTime/HourTest.php | 2 +- .../Calculation/Functions/DateTime/MinuteTest.php | 2 +- .../Calculation/Functions/DateTime/MonthTest.php | 2 +- .../Calculation/Functions/DateTime/SecondTest.php | 2 +- .../Calculation/Functions/DateTime/TimeValueTest.php | 2 +- .../Calculation/Functions/DateTime/YearTest.php | 2 +- .../Calculation/Functions/Logical/IfErrorTest.php | 3 +-- .../Calculation/Functions/Logical/IfNaTest.php | 3 +-- .../Calculation/Functions/MathTrig/EvenTest.php | 2 +- .../Calculation/Functions/MathTrig/FactDoubleTest.php | 2 +- .../Calculation/Functions/MathTrig/FactTest.php | 2 +- .../Calculation/Functions/MathTrig/IntTest.php | 2 +- .../Calculation/Functions/MathTrig/OddTest.php | 2 +- .../Calculation/Functions/MathTrig/SignTest.php | 2 +- .../Calculation/Functions/MathTrig/SqrtPiTest.php | 2 +- .../Calculation/Functions/Statistical/FisherInvTest.php | 2 +- .../Calculation/Functions/Statistical/FisherTest.php | 2 +- .../Calculation/Functions/Statistical/GammaLnTest.php | 2 +- .../Calculation/Functions/TextData/CharTest.php | 2 +- .../Calculation/Functions/TextData/CleanTest.php | 2 +- .../Calculation/Functions/TextData/CodeTest.php | 2 +- .../Calculation/Functions/TextData/LenTest.php | 2 +- .../Calculation/Functions/TextData/LowerTest.php | 2 +- .../Calculation/Functions/TextData/ProperTest.php | 2 +- .../Calculation/Functions/TextData/TTest.php | 2 +- .../Calculation/Functions/TextData/TrimTest.php | 2 +- .../Calculation/Functions/TextData/UpperTest.php | 2 +- .../Calculation/Functions/TextData/ValueTest.php | 2 +- tests/PhpSpreadsheetTests/SpreadsheetTest.php | 4 ++-- 36 files changed, 44 insertions(+), 46 deletions(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php index 2816a6adb1..7506665a44 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateTest.php @@ -21,9 +21,9 @@ protected function setUp(): void * @dataProvider providerDATE * * @param mixed $expectedResult - * @param $year - * @param $month - * @param $day + * @param mixed $year + * @param mixed $month + * @param mixed $day */ public function testDATE($expectedResult, $year, $month, $day): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php index d2a58b0df2..391ec7c840 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php @@ -21,7 +21,7 @@ protected function setUp(): void * @dataProvider providerDATEVALUE * * @param mixed $expectedResult - * @param $dateValue + * @param mixed $dateValue */ public function testDATEVALUE($expectedResult, $dateValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php index 8f4a9dbdd2..22c65fa45e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php @@ -37,7 +37,7 @@ protected function tearDown(): void * * @param mixed $expectedResultExcel * @param mixed $expectedResultOpenOffice - * @param $dateTimeValue + * @param mixed $dateTimeValue */ public function testDAY($expectedResultExcel, $expectedResultOpenOffice, $dateTimeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/Days360Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/Days360Test.php index 47449e0d17..16c3dcdecc 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/Days360Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/Days360Test.php @@ -20,9 +20,9 @@ protected function setUp(): void * @dataProvider providerDAYS360 * * @param mixed $expectedResult - * @param $startDate - * @param $endDate - * @param $method + * @param mixed $startDate + * @param mixed $endDate + * @param mixed $method */ public function testDAYS360($expectedResult, $startDate, $endDate, $method): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DaysTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DaysTest.php index fe31dfcc7e..2c377f3592 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DaysTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DaysTest.php @@ -20,8 +20,8 @@ protected function setUp(): void * @dataProvider providerDAYS * * @param mixed $expectedResult - * @param $endDate - * @param $startDate + * @param mixed $endDate + * @param mixed $startDate */ public function testDAYS($expectedResult, $endDate, $startDate): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index c7e5a37565..f6db99d436 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -21,8 +21,8 @@ protected function setUp(): void * @dataProvider providerEDATE * * @param mixed $expectedResult - * @param $dateValue - * @param $adjustmentMonths + * @param mixed $dateValue + * @param mixed $adjustmentMonths */ public function testEDATE($expectedResult, $dateValue, $adjustmentMonths): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php index 353fcebdd3..10965e87e5 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php @@ -21,8 +21,8 @@ protected function setUp(): void * @dataProvider providerEOMONTH * * @param mixed $expectedResult - * @param $dateValue - * @param $adjustmentMonths + * @param mixed $dateValue + * @param mixed $adjustmentMonths */ public function testEOMONTH($expectedResult, $dateValue, $adjustmentMonths): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/HourTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/HourTest.php index 2d0cd5d1b4..e2575004e2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/HourTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/HourTest.php @@ -20,7 +20,7 @@ protected function setUp(): void * @dataProvider providerHOUR * * @param mixed $expectedResult - * @param $dateTimeValue + * @param mixed $dateTimeValue */ public function testHOUR($expectedResult, $dateTimeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MinuteTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MinuteTest.php index 8472c6de07..9d078ead1b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MinuteTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MinuteTest.php @@ -20,7 +20,7 @@ protected function setUp(): void * @dataProvider providerMINUTE * * @param mixed $expectedResult - * @param $dateTimeValue + * @param mixed $dateTimeValue */ public function testMINUTE($expectedResult, $dateTimeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MonthTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MonthTest.php index 6251370261..be71e2fbeb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MonthTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/MonthTest.php @@ -20,7 +20,7 @@ protected function setUp(): void * @dataProvider providerMONTH * * @param mixed $expectedResult - * @param $dateTimeValue + * @param mixed $dateTimeValue */ public function testMONTH($expectedResult, $dateTimeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/SecondTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/SecondTest.php index bc2b075253..a2f2e2ccd7 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/SecondTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/SecondTest.php @@ -20,7 +20,7 @@ protected function setUp(): void * @dataProvider providerSECOND * * @param mixed $expectedResult - * @param $dateTimeValue + * @param mixed $dateTimeValue */ public function testSECOND($expectedResult, $dateTimeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php index 60e585f3c7..581e55b0ae 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeValueTest.php @@ -21,7 +21,7 @@ protected function setUp(): void * @dataProvider providerTIMEVALUE * * @param mixed $expectedResult - * @param $timeValue + * @param mixed $timeValue */ public function testTIMEVALUE($expectedResult, $timeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearTest.php index bbdaf92a4f..32966663e3 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearTest.php @@ -20,7 +20,7 @@ protected function setUp(): void * @dataProvider providerYEAR * * @param mixed $expectedResult - * @param $dateTimeValue + * @param mixed $dateTimeValue */ public function testYEAR($expectedResult, $dateTimeValue): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php index c1602edacf..cbe79d5d03 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php @@ -17,8 +17,7 @@ protected function setUp(): void * @dataProvider providerIFERROR * * @param mixed $expectedResult - * @param $value - * @param $return + * @param mixed $value */ public function testIFERROR($expectedResult, $value, $return): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php index 2976761a2f..6330245d68 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php @@ -17,8 +17,7 @@ protected function setUp(): void * @dataProvider providerIFNA * * @param mixed $expectedResult - * @param $value - * @param $return + * @param mixed $value */ public function testIFNA($expectedResult, $value, $return): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/EvenTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/EvenTest.php index 96c0b04629..667d973376 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/EvenTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/EvenTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerEVEN * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testEVEN($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactDoubleTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactDoubleTest.php index f0b6b146ac..c6672556b7 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactDoubleTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactDoubleTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerFACTDOUBLE * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testFACTDOUBLE($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php index f609289633..9b2a654ba1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/FactTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerFACT * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testFACT($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php index f400a7feb6..7f182d4097 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/IntTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerINT * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testINT($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/OddTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/OddTest.php index 6c5758c67a..af8f6890eb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/OddTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/OddTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerODD * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testODD($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SignTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SignTest.php index 68f5acb97d..fdb5cf769a 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SignTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SignTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerSIGN * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testSIGN($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SqrtPiTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SqrtPiTest.php index bb4bba4b2a..c49934ea4d 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SqrtPiTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/SqrtPiTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerSQRTPI * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testSQRTPI($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherInvTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherInvTest.php index efd212c8cb..2c3e592c52 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherInvTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherInvTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerFISHERINV * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testFISHERINV($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherTest.php index 788ffc6a59..7705517a91 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/FisherTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerFISHER * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testFISHER($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/GammaLnTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/GammaLnTest.php index d0ae623fbe..31407febc1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/GammaLnTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/GammaLnTest.php @@ -17,7 +17,7 @@ protected function setUp(): void * @dataProvider providerGAMMALN * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testGAMMALN($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CharTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CharTest.php index cf22df024f..324f5054e4 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CharTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CharTest.php @@ -11,7 +11,7 @@ class CharTest extends TestCase * @dataProvider providerCHAR * * @param mixed $expectedResult - * @param $character + * @param mixed $character */ public function testCHAR($expectedResult, $character): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CleanTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CleanTest.php index 31dcc5e659..ddc27a5d94 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CleanTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CleanTest.php @@ -11,7 +11,7 @@ class CleanTest extends TestCase * @dataProvider providerCLEAN * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testCLEAN($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CodeTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CodeTest.php index 9c19f34787..7bf5a00fc2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CodeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/CodeTest.php @@ -11,7 +11,7 @@ class CodeTest extends TestCase * @dataProvider providerCODE * * @param mixed $expectedResult - * @param $character + * @param mixed $character */ public function testCODE($expectedResult, $character): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LenTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LenTest.php index bca2b3894e..c6ffc43db9 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LenTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LenTest.php @@ -11,7 +11,7 @@ class LenTest extends TestCase * @dataProvider providerLEN * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testLEN($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LowerTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LowerTest.php index 9ba677c716..1d7f09e7b3 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LowerTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/LowerTest.php @@ -11,7 +11,7 @@ class LowerTest extends TestCase * @dataProvider providerLOWER * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testLOWER($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ProperTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ProperTest.php index aae0e6962f..bc37d32c4b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ProperTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ProperTest.php @@ -11,7 +11,7 @@ class ProperTest extends TestCase * @dataProvider providerPROPER * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testPROPER($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TTest.php index c7606c0558..e2f5cd015e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TTest.php @@ -11,7 +11,7 @@ class TTest extends TestCase * @dataProvider providerT * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testT($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TrimTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TrimTest.php index 91890dedd1..6b2dbc7a5b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TrimTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/TrimTest.php @@ -11,7 +11,7 @@ class TrimTest extends TestCase * @dataProvider providerTRIM * * @param mixed $expectedResult - * @param $character + * @param mixed $character */ public function testTRIM($expectedResult, $character): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/UpperTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/UpperTest.php index 13fb0b8622..c3eed60990 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/UpperTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/UpperTest.php @@ -11,7 +11,7 @@ class UpperTest extends TestCase * @dataProvider providerUPPER * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testUPPER($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ValueTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ValueTest.php index 355193de4a..607c926b90 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/ValueTest.php @@ -32,7 +32,7 @@ protected function tearDown(): void * @dataProvider providerVALUE * * @param mixed $expectedResult - * @param $value + * @param mixed $value */ public function testVALUE($expectedResult, $value): void { diff --git a/tests/PhpSpreadsheetTests/SpreadsheetTest.php b/tests/PhpSpreadsheetTests/SpreadsheetTest.php index 05fbe1b549..e81e0901dc 100644 --- a/tests/PhpSpreadsheetTests/SpreadsheetTest.php +++ b/tests/PhpSpreadsheetTests/SpreadsheetTest.php @@ -44,8 +44,8 @@ public function dataProviderForSheetNames() } /** - * @param $index - * @param $sheetName + * @param int $index + * @param string $sheetName * * @dataProvider dataProviderForSheetNames */ From 332b1af3f05270f167a413cb07eaf00483daf470 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Mon, 10 Aug 2020 22:15:45 +0200 Subject: [PATCH 33/39] Extra typehinting --- .../Calculation/Functions/Logical/IfErrorTest.php | 1 + .../Calculation/Functions/Logical/IfNaTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php index cbe79d5d03..cf3a39d424 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php @@ -18,6 +18,7 @@ protected function setUp(): void * * @param mixed $expectedResult * @param mixed $value + * @param mixed $return */ public function testIFERROR($expectedResult, $value, $return): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php index 6330245d68..6330227633 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php @@ -18,6 +18,7 @@ protected function setUp(): void * * @param mixed $expectedResult * @param mixed $value + * @param mixed $return */ public function testIFNA($expectedResult, $value, $return): void { From 9741159390988dd20927196dd30a624086859322 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Tue, 11 Aug 2020 18:17:34 +0200 Subject: [PATCH 34/39] Extra typehinting --- .../Calculation/Calculation.php | 4 ++- src/PhpSpreadsheet/Calculation/TextData.php | 26 +++++++++---------- src/PhpSpreadsheet/Shared/Date.php | 2 +- .../Calculation/CalculationTest.php | 4 +-- .../Functions/DateTime/DateDifTest.php | 6 ++--- .../Functions/Engineering/ImConjugateTest.php | 2 +- .../Functions/Engineering/ImCosTest.php | 2 +- .../Functions/Engineering/ImCoshTest.php | 2 +- .../Functions/Engineering/ImCotTest.php | 2 +- .../Functions/Engineering/ImCscTest.php | 2 +- .../Functions/Engineering/ImCschTest.php | 2 +- .../Functions/Engineering/ImDivTest.php | 2 +- .../Functions/Engineering/ImExpTest.php | 2 +- .../Functions/Engineering/ImLnTest.php | 2 +- .../Functions/Engineering/ImLog10Test.php | 2 +- .../Functions/Engineering/ImLog2Test.php | 2 +- .../Functions/Engineering/ImPowerTest.php | 2 +- .../Functions/Engineering/ImProductTest.php | 2 +- .../Functions/Engineering/ImSecTest.php | 2 +- .../Functions/Engineering/ImSechTest.php | 2 +- .../Functions/Engineering/ImSinTest.php | 2 +- .../Functions/Engineering/ImSinhTest.php | 2 +- .../Functions/Engineering/ImSqrtTest.php | 2 +- .../Functions/Engineering/ImSubTest.php | 2 +- .../Functions/Engineering/ImSumTest.php | 2 +- .../Functions/Engineering/ImTanTest.php | 2 +- 26 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 9709c1577d..21dbf69b64 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -216,7 +216,7 @@ class Calculation * Excel constant string translations to their PHP equivalents * Constant conversion from text name/value to actual (datatyped) value. * - * @var string[] + * @var mixed[] */ private static $excelConstants = [ 'TRUE' => true, @@ -3687,6 +3687,8 @@ private function showTypeDetails($value) return $typeString . ' with a value of ' . $this->showValue($value); } + + return null; } /** diff --git a/src/PhpSpreadsheet/Calculation/TextData.php b/src/PhpSpreadsheet/Calculation/TextData.php index da958836ce..aa8b065c55 100644 --- a/src/PhpSpreadsheet/Calculation/TextData.php +++ b/src/PhpSpreadsheet/Calculation/TextData.php @@ -61,7 +61,7 @@ public static function TRIMNONPRINTABLE($stringValue = '') return str_replace(self::$invalidChars, '', trim($stringValue, "\x00..\x1F")); } - return null; + return ''; } /** @@ -82,7 +82,7 @@ public static function TRIMSPACES($stringValue = '') return trim(preg_replace('/ +/', ' ', trim($stringValue, ' ')), ' '); } - return null; + return ''; } private static function convertBooleanValue($value) @@ -97,7 +97,7 @@ private static function convertBooleanValue($value) /** * ASCIICODE. * - * @param string $characters Value + * @param ?string $characters Value * * @return int|string A string if arguments are invalid */ @@ -146,8 +146,8 @@ public static function CONCATENATE(...$args) * This function converts a number to text using currency format, with the decimals rounded to the specified place. * The format used is $#,##0.00_);($#,##0.00).. * - * @param float $value The value to format - * @param int $decimals The number of digits to display to the right of the decimal point. + * @param ?float $value The value to format + * @param ?int $decimals The number of digits to display to the right of the decimal point. * If decimals is negative, number is rounded to the left of the decimal point. * If you omit decimals, it is assumed to be 2 * @@ -166,13 +166,13 @@ public static function DOLLAR($value = 0, $decimals = 2) $mask = '$#,##0'; if ($decimals > 0) { - $mask .= '.' . str_repeat('0', $decimals); + $mask .= '.' . str_repeat('0', (int) $decimals); } else { $round = 10 ** abs($decimals); if ($value < 0) { $round = 0 - $round; } - $value = MathTrig::MROUND($value, $round); + $value = MathTrig::MROUND($value, (int) $round); } return NumberFormat::toFormattedString($value, $mask); @@ -185,7 +185,7 @@ public static function DOLLAR($value = 0, $decimals = 2) * @param string $haystack The string in which to look * @param int $offset Offset within $haystack * - * @return string + * @return ExcelException|int */ public static function SEARCHSENSITIVE($needle, $haystack, $offset = 1) { @@ -220,7 +220,7 @@ public static function SEARCHSENSITIVE($needle, $haystack, $offset = 1) * @param string $haystack The string in which to look * @param int $offset Offset within $haystack * - * @return string + * @return ExcelException|int */ public static function SEARCHINSENSITIVE($needle, $haystack, $offset = 1) { @@ -544,7 +544,7 @@ public static function TEXTFORMAT($value, $format) * * @param mixed $value Value to check * - * @return DateTimeInterface|float|int|string A string if arguments are invalid + * @return DateTimeInterface|ExcelException|float|int An ExcelException if arguments are invalid */ public static function VALUE($value = '') { @@ -592,7 +592,7 @@ public static function VALUE($value = '') * @param string $decimalSeparator decimal separator, defaults to locale defined value * @param string $groupSeparator group/thosands separator, defaults to locale defined value * - * @return float|string + * @return ExcelException|float */ public static function NUMBERVALUE($value = '', $decimalSeparator = null, $groupSeparator = null) { @@ -636,8 +636,8 @@ public static function NUMBERVALUE($value = '', $decimalSeparator = null, $group * EXACT is case-sensitive but ignores formatting differences. * Use EXACT to test text being entered into a document. * - * @param $value1 - * @param $value2 + * @param mixed $value1 + * @param mixed $value2 * * @return bool */ diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index ffbe74e353..ae0e79fb4a 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -159,7 +159,7 @@ private static function validateTimeZone($timeZone) * if you don't want to treat it as a UTC value * Use the default (UST) unless you absolutely need a conversion * - * @return DateTimeInterface + * @return \DateTime * PHP date/time object */ public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) diff --git a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php index 54881f9512..f80c65d358 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php @@ -311,8 +311,8 @@ public function testBranchPruningFormulaParsingInequalitiesConditionsCase(): voi } /** - * @param $expectedResult - * @param $dataArray + * @param mixed $expectedResult + * @param mixed $dataArray * @param string $formula * @param string $cellCoordinates where to put the formula * @param string[] $shouldBeSetInCacheCells coordinates of cells that must diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php index c873ccfbe6..7f0a639d2b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php @@ -20,9 +20,9 @@ protected function setUp(): void * @dataProvider providerDATEDIF * * @param mixed $expectedResult - * @param $startDate - * @param $endDate - * @param $unit + * @param mixed $startDate + * @param mixed $endDate + * @param mixed $unit */ public function testDATEDIF($expectedResult, $startDate, $endDate, $unit): void { diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php index bc3a39187e..583a2adc29 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php @@ -12,7 +12,7 @@ class ImConjugateTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php index 693f0babc8..ec08b17e28 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php @@ -12,7 +12,7 @@ class ImCosTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php index ae035fef7d..f8c2b5d72f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php @@ -12,7 +12,7 @@ class ImCoshTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php index 8b888b3fd4..5d371252c0 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php @@ -12,7 +12,7 @@ class ImCotTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php index 5a08c0b60e..b03e022c8b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php @@ -12,7 +12,7 @@ class ImCscTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php index a95a4eafb1..09f9040a94 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php @@ -12,7 +12,7 @@ class ImCschTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php index d429e58f8a..d2352fa0a6 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php @@ -12,7 +12,7 @@ class ImDivTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php index 7debbc9c23..a9b3b5ae66 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php @@ -12,7 +12,7 @@ class ImExpTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php index 4875b310b1..150dac26cf 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php @@ -12,7 +12,7 @@ class ImLnTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php index fe4e821b31..983aed9885 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php @@ -12,7 +12,7 @@ class ImLog10Test extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php index 76207492c9..a4041f07d9 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php @@ -12,7 +12,7 @@ class ImLog2Test extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php index 1f72895032..31e3f11819 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php @@ -12,7 +12,7 @@ class ImPowerTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php index 77866824fe..24ff0014fc 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php @@ -12,7 +12,7 @@ class ImProductTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php index e785d3ac6c..7626f676eb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php @@ -12,7 +12,7 @@ class ImSecTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php index 22cb6faecf..5187aa9d6e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php @@ -12,7 +12,7 @@ class ImSechTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php index dd797a3522..5e264d8076 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php @@ -12,7 +12,7 @@ class ImSinTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php index 4174d1c05f..1383d8f260 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php @@ -12,7 +12,7 @@ class ImSinhTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php index 091b11c5f5..4d9196804a 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php @@ -12,7 +12,7 @@ class ImSqrtTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php index 82713576ae..1b66721d47 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php @@ -12,7 +12,7 @@ class ImSubTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php index 6fd1ce6f9e..588f33bf5f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php @@ -12,7 +12,7 @@ class ImSumTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php index 57b238155d..9f76cac8f2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php @@ -12,7 +12,7 @@ class ImTanTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ComplexAssert + * @var ?ComplexAssert */ protected $complexAssert; From 2426c59e6b22ce59846826b2683eb95a1bf6e0de Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 12 Aug 2020 00:23:47 +0200 Subject: [PATCH 35/39] Extra typehinting --- src/PhpSpreadsheet/Calculation/DateTime.php | 18 +++--- .../Calculation/Engineering.php | 44 ++++++------- src/PhpSpreadsheet/Calculation/Financial.php | 8 ++- src/PhpSpreadsheet/Calculation/LookupRef.php | 62 ++++++++++--------- src/PhpSpreadsheet/Calculation/MathTrig.php | 32 +++++----- .../Calculation/Statistical.php | 10 ++- 6 files changed, 94 insertions(+), 80 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index bd17959f35..49ea322138 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -471,7 +471,7 @@ public static function TIME($hour = 0, $minute = 0, $second = 0) * depending on the value of the ReturnDateType flag * or an ExcelException if the value cannot be converted */ - public static function DATEVALUE($dateValue = 1) + public static function DATEVALUE($dateValue = '1') { $dateValue = trim(Functions::flattenSingleValue($dateValue), '"'); // Strip any ordinals because they're allowed in Excel (English only) @@ -840,14 +840,14 @@ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) // Execute function $PHPStartDateObject = Date::excelToDateTimeObject($startDate); - $startDay = $PHPStartDateObject->format('j'); - $startMonth = $PHPStartDateObject->format('n'); - $startYear = $PHPStartDateObject->format('Y'); + $startDay = (int) $PHPStartDateObject->format('j'); + $startMonth = (int) $PHPStartDateObject->format('n'); + $startYear = (int) $PHPStartDateObject->format('Y'); $PHPEndDateObject = Date::excelToDateTimeObject($endDate); - $endDay = $PHPEndDateObject->format('j'); - $endMonth = $PHPEndDateObject->format('n'); - $endYear = $PHPEndDateObject->format('Y'); + $endDay = (int) $PHPEndDateObject->format('j'); + $endMonth = (int) $PHPEndDateObject->format('n'); + $endYear = (int) $PHPEndDateObject->format('Y'); return self::dateDiff360($startDay, $startMonth, $startYear, $endDay, $endMonth, $endYear, !$method); } @@ -1001,11 +1001,11 @@ public static function NETWORKDAYS($startDate, $endDate, ...$dateArgs) } // Execute function - $startDoW = 6 - self::WEEKDAY($startDate, 2); + $startDoW = 6 - self::WEEKDAY((int) $startDate, 2); if ($startDoW < 0) { $startDoW = 0; } - $endDoW = self::WEEKDAY($endDate, 2); + $endDoW = self::WEEKDAY((int) $endDate, 2); if ($endDoW >= 6) { $endDoW = 0; } diff --git a/src/PhpSpreadsheet/Calculation/Engineering.php b/src/PhpSpreadsheet/Calculation/Engineering.php index 00568a9024..a44dbbef96 100644 --- a/src/PhpSpreadsheet/Calculation/Engineering.php +++ b/src/PhpSpreadsheet/Calculation/Engineering.php @@ -783,7 +783,7 @@ private static function nbrConversionFormat($xVal, $places) * If $ord is nonnumeric, BESSELI returns the #VALUE! error value. * If $ord < 0, BESSELI returns the #NUM! error value. * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function BESSELI($x, $ord) { @@ -835,7 +835,7 @@ public static function BESSELI($x, $ord) * If $ord is nonnumeric, BESSELJ returns the #VALUE! error value. * If $ord < 0, BESSELJ returns the #NUM! error value. * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function BESSELJ($x, $ord) { @@ -926,7 +926,7 @@ private static function besselK1($fNum) * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. * If $ord < 0, BESSELK returns the #NUM! error value. * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function BESSELK($x, $ord) { @@ -1013,7 +1013,7 @@ private static function besselY1($fNum) * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. * If $ord < 0, BESSELK returns the #NUM! error value. * - * @return float|string Result, or a string containing an error + * @return ExcelException|float Result, or an ExcelException containing an error */ public static function BESSELY($x, $ord) { @@ -1066,7 +1066,7 @@ public static function BESSELY($x, $ord) * If number is not a valid binary number, or if number contains more than * 10 characters (10 bits), BIN2DEC returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function BINTODEC($x) { @@ -1095,7 +1095,7 @@ public static function BINTODEC($x) return '-' . (512 - bindec($x)); } - return bindec($x); + return (string) bindec($x); } /** @@ -1119,7 +1119,7 @@ public static function BINTODEC($x) * If places is nonnumeric, BIN2HEX returns the #VALUE! error value. * If places is negative, BIN2HEX returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function BINTOHEX($x, $places = null) { @@ -1173,7 +1173,7 @@ public static function BINTOHEX($x, $places = null) * If places is nonnumeric, BIN2OCT returns the #VALUE! error value. * If places is negative, BIN2OCT returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function BINTOOCT($x, $places = null) { @@ -1230,7 +1230,7 @@ public static function BINTOOCT($x, $places = null) * If places is nonnumeric, DEC2BIN returns the #VALUE! error value. * If places is zero or negative, DEC2BIN returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function DECTOBIN($x, $places = null) { @@ -1289,7 +1289,7 @@ public static function DECTOBIN($x, $places = null) * If places is nonnumeric, DEC2HEX returns the #VALUE! error value. * If places is zero or negative, DEC2HEX returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function DECTOHEX($x, $places = null) { @@ -1396,7 +1396,7 @@ public static function DECTOOCT($x, $places = null) * If places is nonnumeric, HEX2BIN returns the #VALUE! error value. * If places is negative, HEX2BIN returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function HEXTOBIN($x, $places = null) { @@ -1430,7 +1430,7 @@ public static function HEXTOBIN($x, $places = null) * If number is not a valid hexadecimal number, HEX2DEC returns the * #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function HEXTODEC($x) { @@ -1457,10 +1457,10 @@ public static function HEXTODEC($x) $binX[$i] = ($binX[$i] == '1' ? '0' : '1'); } - return (bindec($binX) + 1) * -1; + return (string) ((bindec($binX) + 1) * -1); } - return bindec($binX); + return (string) bindec($binX); } /** @@ -1492,7 +1492,7 @@ public static function HEXTODEC($x) * value. * If places is negative, HEX2OCT returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function HEXTOOCT($x, $places = null) { @@ -1508,7 +1508,7 @@ public static function HEXTOOCT($x, $places = null) } $decimal = self::HEXTODEC($x); - if ($decimal < -536870912 || $decimal > 536870911) { + if ((int) $decimal < -536870912 || (int) $decimal > 536870911) { return Functions::NAN(); } @@ -1546,7 +1546,7 @@ public static function HEXTOOCT($x, $places = null) * If places is negative, OCT2BIN returns the #NUM! error * value. * - * @return string + * @return ExcelException|string */ public static function OCTTOBIN($x, $places = null) { @@ -1580,7 +1580,7 @@ public static function OCTTOBIN($x, $places = null) * If number is not a valid octal number, OCT2DEC returns the * #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function OCTTODEC($x) { @@ -1602,10 +1602,10 @@ public static function OCTTODEC($x) $binX[$i] = ($binX[$i] == '1' ? '0' : '1'); } - return (bindec($binX) + 1) * -1; + return (string) ((bindec($binX) + 1) * -1); } - return bindec($binX); + return (string) bindec($binX); } /** @@ -1634,7 +1634,7 @@ public static function OCTTODEC($x) * If places is nonnumeric, OCT2HEX returns the #VALUE! error value. * If places is negative, OCT2HEX returns the #NUM! error value. * - * @return string + * @return ExcelException|string */ public static function OCTTOHEX($x, $places = null) { @@ -1666,7 +1666,7 @@ public static function OCTTOHEX($x, $places = null) * @param string $suffix The suffix for the imaginary component of the complex number. * If omitted, the suffix is assumed to be "i". * - * @return string + * @return ExcelException|string */ public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i') { diff --git a/src/PhpSpreadsheet/Calculation/Financial.php b/src/PhpSpreadsheet/Calculation/Financial.php index 49562dc5ab..f66ea2cf8b 100644 --- a/src/PhpSpreadsheet/Calculation/Financial.php +++ b/src/PhpSpreadsheet/Calculation/Financial.php @@ -320,7 +320,7 @@ public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $per * 3 Actual/365 * 4 European 30/360 * - * @return float + * @return ExcelException|float */ public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0) { @@ -336,7 +336,13 @@ public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $peri $fCostDelta = $cost - $salvage; // Note, quirky variation for leap years on the YEARFRAC for this function $purchasedYear = DateTime::YEAR($purchased); + if ($purchasedYear instanceof ExcelException) { + return $purchasedYear; + } $yearFrac = DateTime::YEARFRAC($purchased, $firstPeriod, $basis); + if ($yearFrac instanceof ExcelException) { + return $yearFrac; + } if (($basis == 1) && ($yearFrac < 1) && (DateTime::isLeapYear($purchasedYear))) { $yearFrac *= 365 / 366; diff --git a/src/PhpSpreadsheet/Calculation/LookupRef.php b/src/PhpSpreadsheet/Calculation/LookupRef.php index 45aa923964..1bc3766c74 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef.php @@ -97,23 +97,24 @@ public static function COLUMN($cellAddress = null) return (int) Coordinate::columnIndexFromString($columnKey); } - } else { - [$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); - if (strpos($cellAddress, ':') !== false) { - [$startAddress, $endAddress] = explode(':', $cellAddress); - $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); - $endAddress = preg_replace('/[^a-z]/i', '', $endAddress); - $returnValue = []; - do { - $returnValue[] = (int) Coordinate::columnIndexFromString($startAddress); - } while ($startAddress++ != $endAddress); - - return $returnValue; - } - $cellAddress = preg_replace('/[^a-z]/i', '', $cellAddress); + } - return (int) Coordinate::columnIndexFromString($cellAddress); + [$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); + if (strpos($cellAddress, ':') !== false) { + [$startAddress, $endAddress] = explode(':', $cellAddress); + $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); + $endAddress = preg_replace('/[^a-z]/i', '', $endAddress); + $returnValue = []; + do { + $returnValue[] = (int) Coordinate::columnIndexFromString($startAddress); + } while ($startAddress++ != $endAddress); + + return $returnValue; } + + $cellAddress = preg_replace('/[^a-z]/i', '', $cellAddress); + + return (int) Coordinate::columnIndexFromString($cellAddress); } /** @@ -174,23 +175,24 @@ public static function ROW($cellAddress = null) return (int) preg_replace('/\D/', '', $rowKey); } } - } else { - [$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); - if (strpos($cellAddress, ':') !== false) { - [$startAddress, $endAddress] = explode(':', $cellAddress); - $startAddress = preg_replace('/\D/', '', $startAddress); - $endAddress = preg_replace('/\D/', '', $endAddress); - $returnValue = []; - do { - $returnValue[][] = (int) $startAddress; - } while ($startAddress++ != $endAddress); - - return $returnValue; - } - [$cellAddress] = explode(':', $cellAddress); + } - return (int) preg_replace('/\D/', '', $cellAddress); + [$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); + if (strpos($cellAddress, ':') !== false) { + [$startAddress, $endAddress] = explode(':', $cellAddress); + $startAddress = preg_replace('/\D/', '', $startAddress); + $endAddress = preg_replace('/\D/', '', $endAddress); + $returnValue = []; + do { + $returnValue[][] = (int) $startAddress; + } while ($startAddress++ != $endAddress); + + return $returnValue; } + + [$cellAddress] = explode(':', $cellAddress); + + return (int) preg_replace('/\D/', '', $cellAddress); } /** diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index 0150e3ecdb..04d5d341e3 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -219,7 +219,7 @@ public static function BASE($number, $radix, $minLength = null) * @param float $number the number you want to round * @param float $significance the multiple to which you want to round * - * @return float|string Rounded Number, or a string containing an error + * @return ExcelException|float Rounded Number, or an ExcelException containing an error */ public static function CEILING($number, $significance = null) { @@ -258,7 +258,7 @@ public static function CEILING($number, $significance = null) * @param int $numObjs Number of different objects * @param int $numInSet Number of objects in each combination * - * @return int|string Number of combinations, or a string containing an error + * @return ExcelException|float Number of combinations, or an ExcelException containing an error */ public static function COMBIN($numObjs, $numInSet) { @@ -292,7 +292,7 @@ public static function COMBIN($numObjs, $numInSet) * * @param float $number Number to round * - * @return int|string Rounded Number, or a string containing an error + * @return ExcelException|int Rounded Number, or an ExcelException containing an error */ public static function EVEN($number) { @@ -324,7 +324,7 @@ public static function EVEN($number) * * @param float $factVal Factorial Value * - * @return int|string Factorial, or a string containing an error + * @return ExcelException|int Factorial, or an ExcelException containing an error */ public static function FACT($factVal) { @@ -363,7 +363,7 @@ public static function FACT($factVal) * * @param float $factVal Factorial Value * - * @return int|string Double Factorial, or a string containing an error + * @return ExcelException|int Double Factorial, or an ExcelException containing an error */ public static function FACTDOUBLE($factVal) { @@ -397,7 +397,7 @@ public static function FACTDOUBLE($factVal) * @param float $number Number to round * @param float $significance Significance * - * @return float|string Rounded Number, or a string containing an error + * @return ExcelException|float Rounded Number, or an ExcelException containing an error */ public static function FLOOR($number, $significance = null) { @@ -440,7 +440,7 @@ public static function FLOOR($number, $significance = null) * @param float $significance Significance * @param int $mode direction to round negative numbers * - * @return float|string Rounded Number, or a string containing an error + * @return ExcelException|float Rounded Number, or an ExcelException containing an error */ public static function FLOORMATH($number, $significance = null, $mode = 0) { @@ -478,7 +478,7 @@ public static function FLOORMATH($number, $significance = null, $mode = 0) * @param float $number Number to round * @param float $significance Significance * - * @return float|string Rounded Number, or a string containing an error + * @return ExcelException|float Rounded Number, or an ExcelException containing an error */ public static function FLOORPRECISE($number, $significance = 1) { @@ -547,7 +547,7 @@ public static function GCD(...$args) * * @param float $number Number to cast to an integer * - * @return int|string Integer value, or a string containing an error + * @return ExcelException|int Integer value, or an ExcelException containing an error */ public static function INT($number) { @@ -578,7 +578,7 @@ public static function INT($number) * * @param mixed ...$args Data values * - * @return int|string Lowest Common Multiplier, or a string containing an error + * @return ExcelException|int Lowest Common Multiplier, or an ExcelException containing an error */ public static function LCM(...$args) { @@ -628,7 +628,7 @@ public static function LCM(...$args) * @param float $number The positive real number for which you want the logarithm * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10. * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function logBase($number = null, $base = 10) { @@ -655,7 +655,7 @@ public static function logBase($number = null, $base = 10) * * @param array $matrixValues A matrix of values * - * @return float|string The result, or a string containing an error + * @return ExcelException|float The result, or an ExcelException containing an error */ public static function MDETERM($matrixValues) { @@ -705,7 +705,7 @@ public static function MDETERM($matrixValues) * * @param array $matrixValues A matrix of values * - * @return array|string The result, or a string containing an error + * @return ExcelException|array The result, or an ExcelException containing an error */ public static function MINVERSE($matrixValues) { @@ -755,7 +755,7 @@ public static function MINVERSE($matrixValues) * @param array $matrixData1 A matrix of values * @param array $matrixData2 A matrix of values * - * @return array|string The result, or a string containing an error + * @return ExcelException|array The result, or an ExcelException containing an error */ public static function MMULT($matrixData1, $matrixData2) { @@ -817,14 +817,14 @@ public static function MMULT($matrixData1, $matrixData2) * @param int $a Dividend * @param int $b Divisor * - * @return int|string Remainder, or a string containing an error + * @return ExcelException|float Remainder, or an ExcelException containing an error */ public static function MOD($a = 1, $b = 1) { $a = (float) Functions::flattenSingleValue($a); $b = (float) Functions::flattenSingleValue($b); - if ($b == 0.0) { + if ($b === 0.0) { return Functions::DIV0(); } elseif (($a < 0.0) && ($b > 0.0)) { return $b - fmod(abs($a), $b); diff --git a/src/PhpSpreadsheet/Calculation/Statistical.php b/src/PhpSpreadsheet/Calculation/Statistical.php index 6e2da6f928..aef6355a94 100644 --- a/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/src/PhpSpreadsheet/Calculation/Statistical.php @@ -827,6 +827,9 @@ public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1 while ((($b - $a) > Functions::PRECISION) && ($i++ < self::MAX_ITERATIONS)) { $guess = ($a + $b) / 2; $result = self::BETADIST($guess, $alpha, $beta); + if ($result instanceof ExcelException) { + return $result; + } if (($result == $probability) || ($result == 0)) { $b = $a; } elseif ($result > $probability) { @@ -3007,10 +3010,10 @@ public static function QUARTILE(...$args) $aArgs = Functions::flattenArray($args); // Calculate - $entry = floor(array_pop($aArgs)); + $entry = array_pop($aArgs); if ((is_numeric($entry)) && (!is_string($entry))) { - $entry /= 4; + $entry = floor($entry) / 4; if (($entry < 0) || ($entry > 1)) { return Functions::NAN(); } @@ -3547,6 +3550,9 @@ public static function TINV($probability, $degrees) while ((abs($dx) > Functions::PRECISION) && ($i++ < self::MAX_ITERATIONS)) { // Apply Newton-Raphson step $result = self::TDIST($x, $degrees, 2); + if ($result instanceof ExcelException) { + return $result; + } $error = $result - $probability; if ($error == 0.0) { $dx = 0; From bf084fc96bb4381751f4dab9d8d73480014e073c Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 12 Aug 2020 00:37:33 +0200 Subject: [PATCH 36/39] Extra typehinting --- src/PhpSpreadsheet/Calculation/MathTrig.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/MathTrig.php b/src/PhpSpreadsheet/Calculation/MathTrig.php index 04d5d341e3..00af4cc034 100644 --- a/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -705,7 +705,7 @@ public static function MDETERM($matrixValues) * * @param array $matrixValues A matrix of values * - * @return ExcelException|array The result, or an ExcelException containing an error + * @return array|ExcelException The result, or an ExcelException containing an error */ public static function MINVERSE($matrixValues) { @@ -755,7 +755,7 @@ public static function MINVERSE($matrixValues) * @param array $matrixData1 A matrix of values * @param array $matrixData2 A matrix of values * - * @return ExcelException|array The result, or an ExcelException containing an error + * @return array|ExcelException The result, or an ExcelException containing an error */ public static function MMULT($matrixData1, $matrixData2) { From 839bd11eea38ab65a567b06b5b2b69dc9b612222 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 12 Aug 2020 14:16:48 +0200 Subject: [PATCH 37/39] Extra typehinting --- .../Calculation/Functions/Engineering/ImConjugateTest.php | 2 +- .../Calculation/Functions/Engineering/ImCosTest.php | 2 +- .../Calculation/Functions/Engineering/ImCoshTest.php | 2 +- .../Calculation/Functions/Engineering/ImCotTest.php | 2 +- .../Calculation/Functions/Engineering/ImCscTest.php | 2 +- .../Calculation/Functions/Engineering/ImCschTest.php | 2 +- .../Calculation/Functions/Engineering/ImDivTest.php | 2 +- .../Calculation/Functions/Engineering/ImExpTest.php | 2 +- .../Calculation/Functions/Engineering/ImLnTest.php | 2 +- .../Calculation/Functions/Engineering/ImLog10Test.php | 2 +- .../Calculation/Functions/Engineering/ImLog2Test.php | 2 +- .../Calculation/Functions/Engineering/ImPowerTest.php | 2 +- .../Calculation/Functions/Engineering/ImProductTest.php | 2 +- .../Calculation/Functions/Engineering/ImSecTest.php | 2 +- .../Calculation/Functions/Engineering/ImSechTest.php | 2 +- .../Calculation/Functions/Engineering/ImSinTest.php | 2 +- .../Calculation/Functions/Engineering/ImSinhTest.php | 2 +- .../Calculation/Functions/Engineering/ImSqrtTest.php | 2 +- .../Calculation/Functions/Engineering/ImSubTest.php | 2 +- .../Calculation/Functions/Engineering/ImSumTest.php | 2 +- .../Calculation/Functions/Engineering/ImTanTest.php | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php index 583a2adc29..bc3a39187e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImConjugateTest.php @@ -12,7 +12,7 @@ class ImConjugateTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php index ec08b17e28..693f0babc8 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCosTest.php @@ -12,7 +12,7 @@ class ImCosTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php index f8c2b5d72f..ae035fef7d 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCoshTest.php @@ -12,7 +12,7 @@ class ImCoshTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php index 5d371252c0..8b888b3fd4 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCotTest.php @@ -12,7 +12,7 @@ class ImCotTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php index b03e022c8b..5a08c0b60e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCscTest.php @@ -12,7 +12,7 @@ class ImCscTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php index 09f9040a94..a95a4eafb1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImCschTest.php @@ -12,7 +12,7 @@ class ImCschTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php index d2352fa0a6..d429e58f8a 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImDivTest.php @@ -12,7 +12,7 @@ class ImDivTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php index a9b3b5ae66..7debbc9c23 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImExpTest.php @@ -12,7 +12,7 @@ class ImExpTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php index 150dac26cf..4875b310b1 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLnTest.php @@ -12,7 +12,7 @@ class ImLnTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php index 983aed9885..fe4e821b31 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog10Test.php @@ -12,7 +12,7 @@ class ImLog10Test extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php index a4041f07d9..76207492c9 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImLog2Test.php @@ -12,7 +12,7 @@ class ImLog2Test extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php index 31e3f11819..1f72895032 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImPowerTest.php @@ -12,7 +12,7 @@ class ImPowerTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php index 24ff0014fc..77866824fe 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImProductTest.php @@ -12,7 +12,7 @@ class ImProductTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php index 7626f676eb..e785d3ac6c 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSecTest.php @@ -12,7 +12,7 @@ class ImSecTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php index 5187aa9d6e..22cb6faecf 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSechTest.php @@ -12,7 +12,7 @@ class ImSechTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php index 5e264d8076..dd797a3522 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinTest.php @@ -12,7 +12,7 @@ class ImSinTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php index 1383d8f260..4174d1c05f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSinhTest.php @@ -12,7 +12,7 @@ class ImSinhTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php index 4d9196804a..091b11c5f5 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSqrtTest.php @@ -12,7 +12,7 @@ class ImSqrtTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php index 1b66721d47..82713576ae 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSubTest.php @@ -12,7 +12,7 @@ class ImSubTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php index 588f33bf5f..6fd1ce6f9e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImSumTest.php @@ -12,7 +12,7 @@ class ImSumTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php index 9f76cac8f2..57b238155d 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Engineering/ImTanTest.php @@ -12,7 +12,7 @@ class ImTanTest extends TestCase const COMPLEX_PRECISION = 1E-8; /** - * @var ?ComplexAssert + * @var ComplexAssert */ protected $complexAssert; From bfe278bca353c15f81fa4af1df04f5f392fef791 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 26 Aug 2020 12:39:56 +0200 Subject: [PATCH 38/39] Extra typehinting --- src/PhpSpreadsheet/Calculation/Logical.php | 18 ++++++------ tests/data/Calculation/Logical/IFNA.php | 32 +++++++++++++++++++--- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/Logical.php b/src/PhpSpreadsheet/Calculation/Logical.php index 8ffbe5c274..be44c7bbac 100644 --- a/src/PhpSpreadsheet/Calculation/Logical.php +++ b/src/PhpSpreadsheet/Calculation/Logical.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Calculation; +use PhpOffice\PhpSpreadsheet\Shared\StringHelper; + class Logical { /** @@ -41,14 +43,14 @@ private static function countTrueValues(array $args) foreach ($args as $arg) { // Is it a boolean value? if (is_bool($arg)) { - $returnValue += $arg; + $returnValue += (int) $arg; } elseif ((is_numeric($arg)) && (!is_string($arg))) { $returnValue += ((int) $arg != 0); } elseif (is_string($arg)) { - $arg = strtoupper($arg); - if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) { + $arg = StringHelper::strToUpper($arg); + if (($arg === 'TRUE') || ($arg === Calculation::getTRUE())) { $arg = true; - } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) { + } elseif (($arg === 'FALSE') || ($arg === Calculation::getFALSE())) { $arg = false; } else { return Functions::VALUE(); @@ -78,7 +80,7 @@ private static function countTrueValues(array $args) * * @param mixed ...$args Data values * - * @return bool|string the logical AND of the arguments + * @return bool|ExcelException the logical AND of the arguments */ public static function logicalAnd(...$args) { @@ -119,7 +121,7 @@ public static function logicalAnd(...$args) * * @param mixed $args Data values * - * @return bool|string the logical OR of the arguments + * @return bool|ExcelException the logical OR of the arguments */ public static function logicalOr(...$args) { @@ -160,7 +162,7 @@ public static function logicalOr(...$args) * * @param mixed $args Data values * - * @return bool|string the logical XOR of the arguments + * @return bool|ExcelException the logical XOR of the arguments */ public static function logicalXor(...$args) { @@ -199,7 +201,7 @@ public static function logicalXor(...$args) * * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE * - * @return bool|string the boolean inverse of the argument + * @return bool|ExcelException the boolean inverse of the argument */ public static function NOT($logical = false) { diff --git a/tests/data/Calculation/Logical/IFNA.php b/tests/data/Calculation/Logical/IFNA.php index e08a049852..c636537b3a 100644 --- a/tests/data/Calculation/Logical/IFNA.php +++ b/tests/data/Calculation/Logical/IFNA.php @@ -3,11 +3,35 @@ use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; return [ - [ - 55, - 55, 'not found', + 'A numeric value should return that value' => [ + 34.5, + 34.5, 'not found', ], - [ + 'A boolean value should return that value' => [ + true, + true, 'not found', + ], + 'A null value should return that value' => [ + null, + null, 'not found', + ], + 'A string value should return that value' => [ + 'Hello World', + 'Hello World', 'not found', + ], + 'A string value containing an error text should return that value' => [ + '#DIV/0!', + '#DIV/0!', 'not found', + ], + 'A string value containing the #N/A error text should return that value' => [ + '#N/A', + '#N/A', 'not found', + ], + 'An Error value should return that error value' => [ + ExcelException::DIV0(), + ExcelException::DIV0(), 'not found', + ], + 'NA() value should return the alternative value' => [ 'not found', ExcelException::NA(), 'not found', ], From 464b57fd2a54b4156c0b14476b4c3d49435d1730 Mon Sep 17 00:00:00 2001 From: Rati Rachvelishvili <45259842+rachvela94@users.noreply.github.com> Date: Fri, 29 Jan 2021 18:16:01 +0400 Subject: [PATCH 39/39] Update NamedFormula.php (#1701) --- src/PhpSpreadsheet/NamedFormula.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpSpreadsheet/NamedFormula.php b/src/PhpSpreadsheet/NamedFormula.php index ffb1c9b480..48c34cea34 100644 --- a/src/PhpSpreadsheet/NamedFormula.php +++ b/src/PhpSpreadsheet/NamedFormula.php @@ -17,7 +17,7 @@ public function __construct( ?Worksheet $scope = null ) { // Validate data - if (empty($formula)) { + if (!isset($formula)) { throw new Exception('Tou must specify a Formula value for a Named Formula'); } parent::__construct($name, $worksheet, $formula, $localOnly, $scope);