diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 99260e3bf1..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, @@ -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,14 +3681,14 @@ private function showTypeDetails($value) } else { if ($value == '') { return 'an empty string'; - } elseif ($value[0] == '#') { - return 'a ' . $value . ' error'; } $typeString = 'a string'; } return $typeString . ' with a value of ' . $this->showValue($value); } + + return null; } /** @@ -4039,9 +4043,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 +4063,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 +4499,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 +4557,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 +4775,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 { @@ -4784,20 +4797,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 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 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!'); - $this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!')); - - return false; - } + 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; } } @@ -4992,7 +4997,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 +5028,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/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/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index bfce2a0250..49ea322138 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,19 +65,24 @@ private static function dateDiff360($startDay, $startMonth, $startYear, $endDay, * * @param mixed $dateValue * - * @return mixed Excel date/time serial value, or string if error + * @return ExcelException|float + * 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::dateTimeToExcel($dateValue); + } + + return Functions::VALUE(); } + + $saveReturnDateType = Functions::getReturnDateType(); + Functions::setReturnDateType(Functions::RETURNDATE_EXCEL); + $dateValue = self::DATEVALUE($dateValue); + Functions::setReturnDateType($saveReturnDateType); } return $dateValue; @@ -86,7 +93,8 @@ 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) { @@ -139,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() { @@ -457,10 +466,12 @@ 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) + public static function DATEVALUE($dateValue = '1') { $dateValue = trim(Functions::flattenSingleValue($dateValue), '"'); // Strip any ordinals because they're allowed in Excel (English only) @@ -586,8 +597,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) { @@ -637,7 +650,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') { @@ -645,10 +658,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(); } @@ -678,7 +693,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': @@ -689,7 +704,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'); @@ -745,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 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) { @@ -753,12 +769,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(); } @@ -802,17 +817,20 @@ 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 whoe days between start date and end date, based on the mode used */ 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(); } @@ -822,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); } @@ -858,7 +876,8 @@ 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) { @@ -866,10 +885,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) { @@ -952,7 +973,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) { @@ -963,11 +984,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); @@ -978,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; } @@ -996,7 +1019,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 +1066,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 +1101,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) { @@ -1135,15 +1161,14 @@ 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) { $dateValue = Functions::flattenSingleValue($dateValue); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } @@ -1177,7 +1202,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) { @@ -1191,9 +1216,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 : self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1294,7 +1318,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) { @@ -1310,11 +1334,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 : self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); - } - if ($dateValue < 0.0) { + } elseif ($dateValue < 0.0) { return Functions::NAN(); } @@ -1345,15 +1368,14 @@ 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) { $dateValue = Functions::flattenSingleValue($dateValue); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1377,16 +1399,14 @@ 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) { $dateValue = Functions::flattenSingleValue($dateValue); - if (empty($dateValue)) { - $dateValue = 1; - } - if (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1410,15 +1430,14 @@ 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) { $dateValue = Functions::flattenSingleValue($dateValue); - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = ($dateValue === null) ? 1 : self::getDateValue($dateValue); + if ($dateValue instanceof ExcelException) { return Functions::VALUE(); } elseif ($dateValue < 0.0) { return Functions::NAN(); @@ -1442,7 +1461,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) { @@ -1456,7 +1475,7 @@ public static function HOUROFDAY($timeValue = 0) } } $timeValue = self::getTimeValue($timeValue); - if (is_string($timeValue)) { + if ($timeValue instanceof ExcelException) { return Functions::VALUE(); } } @@ -1483,7 +1502,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) { @@ -1497,7 +1516,7 @@ public static function MINUTE($timeValue = 0) } } $timeValue = self::getTimeValue($timeValue); - if (is_string($timeValue)) { + if ($timeValue instanceof ExcelException) { return Functions::VALUE(); } } @@ -1524,7 +1543,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) { @@ -1538,7 +1557,7 @@ public static function SECOND($timeValue = 0) } } $timeValue = self::getTimeValue($timeValue); - if (is_string($timeValue)) { + if ($timeValue instanceof ExcelException) { return Functions::VALUE(); } } @@ -1583,7 +1602,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 +1649,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/Engineering.php b/src/PhpSpreadsheet/Calculation/Engineering.php index 1256dd90be..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') { @@ -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) { @@ -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()); } /** @@ -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) { @@ -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; @@ -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) { @@ -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; @@ -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) { @@ -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; @@ -2419,14 +2419,14 @@ public static function BITXOR($number1, $number2) * @param int $number * @param int $shiftAmount * - * @return int|string + * @return ExcelException|int */ 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); @@ -2450,14 +2450,14 @@ public static function BITLSHIFT($number, $shiftAmount) * @param int $number * @param int $shiftAmount * - * @return int|string + * @return ExcelException|int */ 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/ExcelException.php b/src/PhpSpreadsheet/Calculation/ExcelException.php new file mode 100644 index 0000000000..1f5ce4bd4b --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/ExcelException.php @@ -0,0 +1,115 @@ + 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..f66ea2cf8b 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) { @@ -134,9 +134,10 @@ 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); @@ -154,7 +155,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; } @@ -185,9 +186,10 @@ 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 + * The 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); @@ -203,7 +205,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; } @@ -318,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) { @@ -334,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; @@ -379,7 +387,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) { @@ -388,10 +396,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(); } @@ -438,7 +448,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) { @@ -447,10 +457,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(); } @@ -508,7 +520,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) { @@ -517,10 +529,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 +587,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(); } @@ -617,7 +633,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) { @@ -626,10 +642,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 +699,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(); } @@ -717,7 +737,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) { @@ -763,7 +783,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) { @@ -814,7 +834,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) { @@ -880,7 +900,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) { @@ -940,7 +960,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) { @@ -959,7 +979,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; } @@ -983,7 +1003,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) { @@ -1019,7 +1039,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) { @@ -1054,9 +1074,9 @@ 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) + public static function EFFECT($nominal_rate = 0.0, $npery = 0) { $nominal_rate = Functions::flattenSingleValue($nominal_rate); $npery = (int) Functions::flattenSingleValue($npery); @@ -1088,9 +1108,9 @@ 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) + public static function FV($rate = 0, $nper = 0, $pmt = 0.0, $pv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $nper = Functions::flattenSingleValue($nper); @@ -1158,7 +1178,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) { @@ -1177,7 +1197,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; } @@ -1203,9 +1223,9 @@ 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) + public static function IPMT($rate, $per, $nper, $pv, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $per = (int) Functions::flattenSingleValue($per); @@ -1246,7 +1266,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) { @@ -1356,7 +1376,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) { @@ -1398,9 +1418,9 @@ 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) + public static function NOMINAL($effect_rate = 0.0, $npery = 0) { $effect_rate = Functions::flattenSingleValue($effect_rate); $npery = (int) Functions::flattenSingleValue($npery); @@ -1425,9 +1445,9 @@ 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) + 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); @@ -1493,9 +1513,9 @@ 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) + public static function PDURATION($rate = 0.0, $pv = 0.0, $fv = 0.0) { $rate = Functions::flattenSingleValue($rate); $pv = Functions::flattenSingleValue($pv); @@ -1522,9 +1542,9 @@ 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) + 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); @@ -1557,9 +1577,9 @@ 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) + public static function PPMT($rate, $per, $nper, $pv, $fv = 0.0, $type = 0) { $rate = Functions::flattenSingleValue($rate); $per = (int) Functions::flattenSingleValue($per); @@ -1584,10 +1604,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 +1642,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; @@ -1675,7 +1695,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) { @@ -1691,7 +1711,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; } @@ -1721,7 +1741,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) { @@ -1738,23 +1758,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; } @@ -1779,9 +1799,9 @@ 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) + 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); @@ -1829,7 +1849,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) { @@ -1894,7 +1914,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) { @@ -1910,7 +1930,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; } @@ -1930,9 +1950,9 @@ 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) + public static function RRI($nper = 0.0, $pv = 0.0, $fv = 0.0) { $nper = Functions::flattenSingleValue($nper); $pv = Functions::flattenSingleValue($pv); @@ -1957,7 +1977,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) { @@ -1987,7 +2007,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) { @@ -2019,7 +2039,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) { @@ -2029,11 +2049,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(); } @@ -2058,7 +2079,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) { @@ -2066,7 +2087,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(); } @@ -2129,11 +2155,12 @@ public static function TBILLYIELD($settlement, $maturity, $price) if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { ++$maturity; - $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360; - if (!is_numeric($daysBetweenSettlementAndMaturity)) { + $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity); + if ($daysBetweenSettlementAndMaturity instanceof ExcelException) { // return date error return $daysBetweenSettlementAndMaturity; } + $daysBetweenSettlementAndMaturity *= 360; } else { $daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement)); } @@ -2315,9 +2342,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 ''; @@ -2375,7 +2405,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) { @@ -2391,11 +2421,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; } @@ -2426,7 +2456,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) { @@ -2443,23 +2473,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; } diff --git a/src/PhpSpreadsheet/Calculation/Functions.php b/src/PhpSpreadsheet/Calculation/Functions.php index 2e8a7ecfcc..0cd8e6f3c4 100644 --- a/src/PhpSpreadsheet/Calculation/Functions.php +++ b/src/PhpSpreadsheet/Calculation/Functions.php @@ -147,11 +147,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 +162,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 +266,14 @@ public static function ifCondition($condition) * * @param mixed $value Value to check * - * @return bool + * @return ExcelException|int */ 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 +320,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 +338,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 +350,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 +358,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 +372,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 +380,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 +432,7 @@ public static function isText($value = null) { $value = self::flattenSingleValue($value); - return is_string($value) && !self::isError($value); + return is_string($value); } /** @@ -462,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) { @@ -484,10 +476,10 @@ public static function n($value = null) return $value; case 'boolean': return (int) $value; - case 'string': + case 'object': // Errors - if ((strlen($value) > 0) && ($value[0] == '#')) { - return $value; + if ($value instanceof ExcelException) { + return $value->errorName(); } break; @@ -513,7 +505,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 +534,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..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) { @@ -94,7 +96,7 @@ public static function logicalAnd(...$args) $argCount = count($args); $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { + if ($returnValue instanceof ExcelException) { return $returnValue; } @@ -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) { @@ -134,7 +136,7 @@ public static function logicalOr(...$args) }); $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { + if ($returnValue instanceof ExcelException) { return $returnValue; } @@ -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) { @@ -175,7 +177,7 @@ public static function logicalXor(...$args) }); $returnValue = self::countTrueValues($args); - if (is_string($returnValue)) { + if ($returnValue instanceof ExcelException) { return $returnValue; } @@ -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/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 7539659ec2..00af4cc034 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 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 array|string The result, or a string containing an error + * @return array|ExcelException 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); @@ -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 19f40f2d4a..aef6355a94 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) { @@ -581,14 +581,19 @@ 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(); + } + + 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) @@ -620,7 +625,7 @@ public static function AVEDEV(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function AVERAGE(...$args) { @@ -628,6 +633,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) @@ -659,7 +667,7 @@ public static function AVERAGE(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function AVERAGEA(...$args) { @@ -704,7 +712,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 = []) { @@ -754,7 +762,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) { @@ -793,7 +801,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) { @@ -819,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) { @@ -851,7 +862,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) { @@ -893,7 +904,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) { @@ -927,7 +938,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) { @@ -988,7 +999,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) { @@ -1019,7 +1030,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) { @@ -1248,7 +1259,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) { @@ -1281,7 +1292,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 @@ -1406,7 +1417,7 @@ public static function CRITBINOM($trials, $probability, $alpha) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function DEVSQ(...$args) { @@ -1416,7 +1427,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? @@ -1459,7 +1470,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) { @@ -1507,7 +1518,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) { @@ -1548,7 +1559,7 @@ public static function FDIST2($value, $u, $v, $cumulative) * * @param float $value * - * @return float|string + * @return ExcelException|float */ public static function FISHER($value) { @@ -1574,7 +1585,7 @@ public static function FISHER($value) * * @param float $value * - * @return float|string + * @return ExcelException|float */ public static function FISHERINV($value) { @@ -1596,7 +1607,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 bool|ExcelException|float */ public static function FORECAST($xValue, $yValues, $xValues) { @@ -1627,7 +1638,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) { @@ -1651,7 +1662,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) { @@ -1684,7 +1695,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) { @@ -1744,7 +1755,7 @@ public static function GAMMAINV($probability, $alpha, $beta) * * @param float $value * - * @return float|string + * @return ExcelException|float */ public static function GAMMALN($value) { @@ -1769,7 +1780,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) { @@ -1793,7 +1804,7 @@ public static function GAUSS($value) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function GEOMEAN(...$args) { @@ -1853,7 +1864,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) { @@ -1896,7 +1907,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) { @@ -1937,7 +1948,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) { @@ -1968,7 +1979,7 @@ public static function INTERCEPT($yValues, $xValues) * * @param array ...$args Data Series * - * @return float|string + * @return ExcelException|float */ public static function KURT(...$args) { @@ -2013,7 +2024,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) { @@ -2055,7 +2066,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 array|ExcelException|int The result, or an ExcelException containing an error */ public static function LINEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -2114,7 +2125,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 array|ExcelException|int The result, or an ExcelException containing an error */ public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -2177,7 +2188,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 @@ -2210,7 +2221,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) { @@ -2240,7 +2251,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) { @@ -2406,7 +2417,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) { @@ -2627,7 +2638,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) { @@ -2664,7 +2675,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) { @@ -2702,7 +2713,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) { @@ -2735,7 +2746,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) { @@ -2766,7 +2777,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) { @@ -2788,7 +2799,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) { @@ -2808,7 +2819,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) { @@ -2825,7 +2836,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) { @@ -2850,7 +2861,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]; } @@ -2873,7 +2884,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) { @@ -2923,7 +2934,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) { @@ -2953,7 +2964,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) { @@ -2992,17 +3003,17 @@ 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) { $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(); } @@ -3022,7 +3033,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) { @@ -3057,7 +3068,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) { @@ -3088,7 +3099,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) { @@ -3127,7 +3138,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) { @@ -3159,7 +3170,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) { @@ -3200,7 +3211,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) { @@ -3230,7 +3241,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) { @@ -3279,7 +3290,7 @@ public static function STDEV(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function STDEVA(...$args) { @@ -3331,7 +3342,7 @@ public static function STDEVA(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function STDEVP(...$args) { @@ -3378,7 +3389,7 @@ public static function STDEVP(...$args) * * @param mixed ...$args Data values * - * @return float|string + * @return ExcelException|float */ public static function STDEVPA(...$args) { @@ -3428,7 +3439,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) { @@ -3458,7 +3469,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) { @@ -3521,7 +3532,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) { @@ -3539,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; @@ -3615,7 +3629,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) { @@ -3658,7 +3672,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) { @@ -3700,7 +3714,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) { @@ -3755,7 +3769,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) { @@ -3798,7 +3812,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) { @@ -3854,7 +3868,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) { @@ -3888,7 +3902,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) { 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/Cell/DataType.php b/src/PhpSpreadsheet/Cell/DataType.php index ba03579178..b44416d2b2 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])) { + return ExcelException::null(); } - return $pValue; + return ExcelException::fromErrorName($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/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); diff --git a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php index 7daf7230ff..7ea773a2c7 100644 --- a/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php +++ b/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xls; +use PhpOffice\PhpSpreadsheet\Calculation\ExcelException; + class ErrorCode { protected static $map = [ @@ -19,12 +21,12 @@ class ErrorCode * * @param int $code * - * @return bool|string + * @return bool|ExcelException */ 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..ae0e79fb4a 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -4,7 +4,9 @@ use DateTimeInterface; use DateTimeZone; +use Exception; 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; @@ -98,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) { @@ -116,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() { @@ -132,7 +136,8 @@ 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 */ private static function validateTimeZone($timeZone) { @@ -154,26 +159,31 @@ 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 \DateTime + * PHP date/time object */ 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); @@ -189,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; } /** @@ -201,7 +216,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) { @@ -214,8 +230,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) { @@ -235,7 +251,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) { @@ -275,7 +292,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) { @@ -425,7 +443,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) { @@ -438,13 +457,13 @@ public static function stringToExcel($dateValue) $dateValueNew = DateTime::DATEVALUE($dateValue); - if ($dateValueNew === Functions::VALUE()) { + if ($dateValueNew instanceof ExcelException) { return false; } if (strpos($dateValue, ':') !== false) { $timeValue = DateTime::TIMEVALUE($dateValue); - if ($timeValue === Functions::VALUE()) { + if ($timeValue instanceof ExcelException) { return false; } $dateValueNew += $timeValue; @@ -454,11 +473,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) { @@ -474,11 +494,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) { diff --git a/src/PhpSpreadsheet/Shared/Trend/Trend.php b/src/PhpSpreadsheet/Shared/Trend/Trend.php index 1b7b390107..a497e2793f 100644 --- a/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -48,6 +48,14 @@ 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) { // 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..d6ed68fcb2 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()); @@ -1277,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) { @@ -1308,41 +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(); - $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" diff --git a/src/PhpSpreadsheet/Writer/Ods/Content.php b/src/PhpSpreadsheet/Writer/Ods/Content.php index 96e66850df..dab11ac8a6 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..cb84bf7040 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; @@ -826,38 +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; - - // 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 (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 === '') { - // 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); - } - } else { - // We are really not supposed to reach here - $num = pack('d', 0x00); - } - } else { - $num = pack('d', 0x00); - } + $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 @@ -883,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); @@ -898,6 +870,35 @@ private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) } } + /** + * @param $calculatedValue + */ + 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. * 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..f80c65d358 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; @@ -310,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 @@ -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..3bc0f0cada --- /dev/null +++ b/tests/PhpSpreadsheetTests/Calculation/ExcelExceptionTest.php @@ -0,0 +1,34 @@ +expectException(SpreadsheetException::class); + 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..7f0a639d2b 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php @@ -20,14 +20,18 @@ 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 { $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..7506665a44 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; @@ -20,14 +21,19 @@ 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 { $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() @@ -52,8 +58,12 @@ 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 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 51e4f7c0cf..391ec7c840 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateValueTest.php @@ -21,12 +21,16 @@ protected function setUp(): void * @dataProvider providerDATEVALUE * * @param mixed $expectedResult - * @param $dateValue + * @param mixed $dateValue */ 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() @@ -51,8 +55,12 @@ 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 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/DayTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php index 482e068d7e..22c65fa45e 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DayTest.php @@ -37,17 +37,27 @@ protected function tearDown(): void * * @param mixed $expectedResultExcel * @param mixed $expectedResultOpenOffice - * @param $dateTimeValue + * @param mixed $dateTimeValue */ 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/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 a887ba5b63..f6db99d436 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; @@ -20,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 { @@ -48,11 +49,13 @@ 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 + self::assertInstanceOf(DateTimeInterface::class, $result); + /* + * ... 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 f9c54039e1..10965e87e5 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; @@ -20,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 { @@ -51,8 +52,12 @@ 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 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/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/TimeTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/TimeTest.php index 344061d48b..904f4953d7 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,12 @@ 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 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 04b8c05840..581e55b0ae 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; @@ -20,7 +21,7 @@ protected function setUp(): void * @dataProvider providerTIMEVALUE * * @param mixed $expectedResult - * @param $timeValue + * @param mixed $timeValue */ public function testTIMEVALUE($expectedResult, $timeValue): void { @@ -50,8 +51,12 @@ 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 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/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/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/IfErrorTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php index c1602edacf..cf3a39d424 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfErrorTest.php @@ -17,8 +17,8 @@ protected function setUp(): void * @dataProvider providerIFERROR * * @param mixed $expectedResult - * @param $value - * @param $return + * @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 2976761a2f..6330227633 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/IfNaTest.php @@ -17,8 +17,8 @@ protected function setUp(): void * @dataProvider providerIFNA * * @param mixed $expectedResult - * @param $value - * @param $return + * @param mixed $value + * @param mixed $return */ public function testIFNA($expectedResult, $value, $return): void { 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/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/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/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/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/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 */ 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..859c7d4fc8 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 @@ [ + 34.5, + 34.5, 'not found', ], - [ - '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', + ], ]; diff --git a/tests/data/Calculation/Logical/NOT.php b/tests/data/Calculation/Logical/NOT.php index f5e5c95a25..5a6aacf13f 100644 --- a/tests/data/Calculation/Logical/NOT.php +++ b/tests/data/Calculation/Logical/NOT.php @@ -1,5 +1,7 @@