Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Calculation\Information;
   4  
   5  use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
   6  use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
   7  use PhpOffice\PhpSpreadsheet\Calculation\Functions;
   8  use PhpOffice\PhpSpreadsheet\Cell\Cell;
   9  use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  10  use PhpOffice\PhpSpreadsheet\NamedRange;
  11  use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
  12  
  13  class Value
  14  {
  15      use ArrayEnabled;
  16  
  17      /**
  18       * IS_BLANK.
  19       *
  20       * @param mixed $value Value to check
  21       *                      Or can be an array of values
  22       *
  23       * @return array|bool
  24       *         If an array of numbers is passed as an argument, then the returned result will also be an array
  25       *            with the same dimensions
  26       */
  27      public static function isBlank($value = null)
  28      {
  29          if (is_array($value)) {
  30              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
  31          }
  32  
  33          return $value === null;
  34      }
  35  
  36      /**
  37       * IS_REF.
  38       *
  39       * @param mixed $value Value to check
  40       *
  41       * @return bool
  42       */
  43      public static function isRef($value, ?Cell $cell = null)
  44      {
  45          if ($cell === null || $value === $cell->getCoordinate()) {
  46              return false;
  47          }
  48  
  49          $cellValue = Functions::trimTrailingRange($value);
  50          if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/ui', $cellValue) === 1) {
  51              [$worksheet, $cellValue] = Worksheet::extractSheetTitle($cellValue, true);
  52              if (!empty($worksheet) && $cell->getWorksheet()->getParent()->getSheetByName($worksheet) === null) {
  53                  return false;
  54              }
  55              [$column, $row] = Coordinate::indexesFromString($cellValue);
  56              if ($column > 16384 || $row > 1048576) {
  57                  return false;
  58              }
  59  
  60              return true;
  61          }
  62  
  63          $namedRange = $cell->getWorksheet()->getParent()->getNamedRange($value);
  64  
  65          return $namedRange instanceof NamedRange;
  66      }
  67  
  68      /**
  69       * IS_EVEN.
  70       *
  71       * @param mixed $value Value to check
  72       *                      Or can be an array of values
  73       *
  74       * @return array|bool|string
  75       *         If an array of numbers is passed as an argument, then the returned result will also be an array
  76       *            with the same dimensions
  77       */
  78      public static function isEven($value = null)
  79      {
  80          if (is_array($value)) {
  81              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
  82          }
  83  
  84          if ($value === null) {
  85              return ExcelError::NAME();
  86          } elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) {
  87              return ExcelError::VALUE();
  88          }
  89  
  90          return ((int) fmod($value, 2)) === 0;
  91      }
  92  
  93      /**
  94       * IS_ODD.
  95       *
  96       * @param mixed $value Value to check
  97       *                      Or can be an array of values
  98       *
  99       * @return array|bool|string
 100       *         If an array of numbers is passed as an argument, then the returned result will also be an array
 101       *            with the same dimensions
 102       */
 103      public static function isOdd($value = null)
 104      {
 105          if (is_array($value)) {
 106              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
 107          }
 108  
 109          if ($value === null) {
 110              return ExcelError::NAME();
 111          } elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) {
 112              return ExcelError::VALUE();
 113          }
 114  
 115          return ((int) fmod($value, 2)) !== 0;
 116      }
 117  
 118      /**
 119       * IS_NUMBER.
 120       *
 121       * @param mixed $value Value to check
 122       *                      Or can be an array of values
 123       *
 124       * @return array|bool
 125       *         If an array of numbers is passed as an argument, then the returned result will also be an array
 126       *            with the same dimensions
 127       */
 128      public static function isNumber($value = null)
 129      {
 130          if (is_array($value)) {
 131              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
 132          }
 133  
 134          if (is_string($value)) {
 135              return false;
 136          }
 137  
 138          return is_numeric($value);
 139      }
 140  
 141      /**
 142       * IS_LOGICAL.
 143       *
 144       * @param mixed $value Value to check
 145       *                      Or can be an array of values
 146       *
 147       * @return array|bool
 148       *         If an array of numbers is passed as an argument, then the returned result will also be an array
 149       *            with the same dimensions
 150       */
 151      public static function isLogical($value = null)
 152      {
 153          if (is_array($value)) {
 154              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
 155          }
 156  
 157          return is_bool($value);
 158      }
 159  
 160      /**
 161       * IS_TEXT.
 162       *
 163       * @param mixed $value Value to check
 164       *                      Or can be an array of values
 165       *
 166       * @return array|bool
 167       *         If an array of numbers is passed as an argument, then the returned result will also be an array
 168       *            with the same dimensions
 169       */
 170      public static function isText($value = null)
 171      {
 172          if (is_array($value)) {
 173              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
 174          }
 175  
 176          return is_string($value) && !ErrorValue::isError($value);
 177      }
 178  
 179      /**
 180       * IS_NONTEXT.
 181       *
 182       * @param mixed $value Value to check
 183       *                      Or can be an array of values
 184       *
 185       * @return array|bool
 186       *         If an array of numbers is passed as an argument, then the returned result will also be an array
 187       *            with the same dimensions
 188       */
 189      public static function isNonText($value = null)
 190      {
 191          if (is_array($value)) {
 192              return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
 193          }
 194  
 195          return !self::isText($value);
 196      }
 197  
 198      /**
 199       * ISFORMULA.
 200       *
 201       * @param mixed $cellReference The cell to check
 202       * @param ?Cell $cell The current cell (containing this formula)
 203       *
 204       * @return array|bool|string
 205       */
 206      public static function isFormula($cellReference = '', ?Cell $cell = null)
 207      {
 208          if ($cell === null) {
 209              return ExcelError::REF();
 210          }
 211  
 212          $fullCellReference = Functions::expandDefinedName((string) $cellReference, $cell);
 213  
 214          if (strpos($cellReference, '!') !== false) {
 215              $cellReference = Functions::trimSheetFromCellReference($cellReference);
 216              $cellReferences = Coordinate::extractAllCellReferencesInRange($cellReference);
 217              if (count($cellReferences) > 1) {
 218                  return self::evaluateArrayArgumentsSubset([self::class, __FUNCTION__], 1, $cellReferences, $cell);
 219              }
 220          }
 221  
 222          $fullCellReference = Functions::trimTrailingRange($fullCellReference);
 223  
 224          preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $fullCellReference, $matches);
 225  
 226          $fullCellReference = $matches[6] . $matches[7];
 227          $worksheetName = str_replace("''", "'", trim($matches[2], "'"));
 228  
 229          $worksheet = (!empty($worksheetName))
 230              ? $cell->getWorksheet()->getParent()->getSheetByName($worksheetName)
 231              : $cell->getWorksheet();
 232  
 233          return ($worksheet !== null) ? $worksheet->getCell($fullCellReference)->isFormula() : ExcelError::REF();
 234      }
 235  
 236      /**
 237       * N.
 238       *
 239       * Returns a value converted to a number
 240       *
 241       * @param null|mixed $value The value you want converted
 242       *
 243       * @return number|string N converts values listed in the following table
 244       *        If value is or refers to N returns
 245       *        A number            That number value
 246       *        A date              The Excel serialized number of that date
 247       *        TRUE                1
 248       *        FALSE               0
 249       *        An error value      The error value
 250       *        Anything else       0
 251       */
 252      public static function asNumber($value = null)
 253      {
 254          while (is_array($value)) {
 255              $value = array_shift($value);
 256          }
 257  
 258          switch (gettype($value)) {
 259              case 'double':
 260              case 'float':
 261              case 'integer':
 262                  return $value;
 263              case 'boolean':
 264                  return (int) $value;
 265              case 'string':
 266                  //    Errors
 267                  if ((strlen($value) > 0) && ($value[0] == '#')) {
 268                      return $value;
 269                  }
 270  
 271                  break;
 272          }
 273  
 274          return 0;
 275      }
 276  
 277      /**
 278       * TYPE.
 279       *
 280       * Returns a number that identifies the type of a value
 281       *
 282       * @param null|mixed $value The value you want tested
 283       *
 284       * @return number N converts values listed in the following table
 285       *        If value is or refers to N returns
 286       *        A number            1
 287       *        Text                2
 288       *        Logical Value       4
 289       *        An error value      16
 290       *        Array or Matrix     64
 291       */
 292      public static function type($value = null)
 293      {
 294          $value = Functions::flattenArrayIndexed($value);
 295          if (is_array($value) && (count($value) > 1)) {
 296              end($value);
 297              $a = key($value);
 298              //    Range of cells is an error
 299              if (Functions::isCellValue($a)) {
 300                  return 16;
 301              //    Test for Matrix
 302              } elseif (Functions::isMatrixValue($a)) {
 303                  return 64;
 304              }
 305          } elseif (empty($value)) {
 306              //    Empty Cell
 307              return 1;
 308          }
 309  
 310          $value = Functions::flattenSingleValue($value);
 311          if (($value === null) || (is_float($value)) || (is_int($value))) {
 312              return 1;
 313          } elseif (is_bool($value)) {
 314              return 4;
 315          } elseif (is_array($value)) {
 316              return 64;
 317          } elseif (is_string($value)) {
 318              //    Errors
 319              if ((strlen($value) > 0) && ($value[0] == '#')) {
 320                  return 16;
 321              }
 322  
 323              return 2;
 324          }
 325  
 326          return 0;
 327      }
 328  }