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 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Worksheet;
   4  
   5  use PhpOffice\PhpSpreadsheet\Cell\Cell;
   6  use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
   7  use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
   8  
   9  /**
  10   * @extends CellIterator<int>
  11   */
  12  class ColumnCellIterator extends CellIterator
  13  {
  14      /**
  15       * Current iterator position.
  16       *
  17       * @var int
  18       */
  19      private $currentRow;
  20  
  21      /**
  22       * Column index.
  23       *
  24       * @var int
  25       */
  26      private $columnIndex;
  27  
  28      /**
  29       * Start position.
  30       *
  31       * @var int
  32       */
  33      private $startRow = 1;
  34  
  35      /**
  36       * End position.
  37       *
  38       * @var int
  39       */
  40      private $endRow = 1;
  41  
  42      /**
  43       * Create a new row iterator.
  44       *
  45       * @param Worksheet $worksheet The worksheet to iterate over
  46       * @param string $columnIndex The column that we want to iterate
  47       * @param int $startRow The row number at which to start iterating
  48       * @param int $endRow Optionally, the row number at which to stop iterating
  49       */
  50      public function __construct(Worksheet $worksheet, $columnIndex = 'A', $startRow = 1, $endRow = null)
  51      {
  52          // Set subject
  53          $this->worksheet = $worksheet;
  54          $this->cellCollection = $worksheet->getCellCollection();
  55          $this->columnIndex = Coordinate::columnIndexFromString($columnIndex);
  56          $this->resetEnd($endRow);
  57          $this->resetStart($startRow);
  58      }
  59  
  60      /**
  61       * (Re)Set the start row and the current row pointer.
  62       *
  63       * @param int $startRow The row number at which to start iterating
  64       *
  65       * @return $this
  66       */
  67      public function resetStart(int $startRow = 1)
  68      {
  69          $this->startRow = $startRow;
  70          $this->adjustForExistingOnlyRange();
  71          $this->seek($startRow);
  72  
  73          return $this;
  74      }
  75  
  76      /**
  77       * (Re)Set the end row.
  78       *
  79       * @param int $endRow The row number at which to stop iterating
  80       *
  81       * @return $this
  82       */
  83      public function resetEnd($endRow = null)
  84      {
  85          $this->endRow = $endRow ?: $this->worksheet->getHighestRow();
  86          $this->adjustForExistingOnlyRange();
  87  
  88          return $this;
  89      }
  90  
  91      /**
  92       * Set the row pointer to the selected row.
  93       *
  94       * @param int $row The row number to set the current pointer at
  95       *
  96       * @return $this
  97       */
  98      public function seek(int $row = 1)
  99      {
 100          if (
 101              $this->onlyExistingCells &&
 102              (!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->columnIndex) . $row))
 103          ) {
 104              throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
 105          }
 106          if (($row < $this->startRow) || ($row > $this->endRow)) {
 107              throw new PhpSpreadsheetException("Row $row is out of range ({$this->startRow} - {$this->endRow})");
 108          }
 109          $this->currentRow = $row;
 110  
 111          return $this;
 112      }
 113  
 114      /**
 115       * Rewind the iterator to the starting row.
 116       */
 117      public function rewind(): void
 118      {
 119          $this->currentRow = $this->startRow;
 120      }
 121  
 122      /**
 123       * Return the current cell in this worksheet column.
 124       */
 125      public function current(): ?Cell
 126      {
 127          $cellAddress = Coordinate::stringFromColumnIndex($this->columnIndex) . $this->currentRow;
 128  
 129          return $this->cellCollection->has($cellAddress)
 130              ? $this->cellCollection->get($cellAddress)
 131              : $this->worksheet->createNewCell($cellAddress);
 132      }
 133  
 134      /**
 135       * Return the current iterator key.
 136       */
 137      public function key(): int
 138      {
 139          return $this->currentRow;
 140      }
 141  
 142      /**
 143       * Set the iterator to its next value.
 144       */
 145      public function next(): void
 146      {
 147          $columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
 148          do {
 149              ++$this->currentRow;
 150          } while (
 151              ($this->onlyExistingCells) &&
 152              ($this->currentRow <= $this->endRow) &&
 153              (!$this->cellCollection->has($columnAddress . $this->currentRow))
 154          );
 155      }
 156  
 157      /**
 158       * Set the iterator to its previous value.
 159       */
 160      public function prev(): void
 161      {
 162          $columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
 163          do {
 164              --$this->currentRow;
 165          } while (
 166              ($this->onlyExistingCells) &&
 167              ($this->currentRow >= $this->startRow) &&
 168              (!$this->cellCollection->has($columnAddress . $this->currentRow))
 169          );
 170      }
 171  
 172      /**
 173       * Indicate if more rows exist in the worksheet range of rows that we're iterating.
 174       */
 175      public function valid(): bool
 176      {
 177          return $this->currentRow <= $this->endRow && $this->currentRow >= $this->startRow;
 178      }
 179  
 180      /**
 181       * Validate start/end values for "IterateOnlyExistingCells" mode, and adjust if necessary.
 182       */
 183      protected function adjustForExistingOnlyRange(): void
 184      {
 185          if ($this->onlyExistingCells) {
 186              $columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
 187              while (
 188                  (!$this->cellCollection->has($columnAddress . $this->startRow)) &&
 189                  ($this->startRow <= $this->endRow)
 190              ) {
 191                  ++$this->startRow;
 192              }
 193              while (
 194                  (!$this->cellCollection->has($columnAddress . $this->endRow)) &&
 195                  ($this->endRow >= $this->startRow)
 196              ) {
 197                  --$this->endRow;
 198              }
 199          }
 200      }
 201  }