ColumnCellIterator.php 5.4 KB

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