Merge branch 'master' into Performance-Ods-Writer

This commit is contained in:
Mark Baker 2022-05-06 12:32:13 +02:00 committed by GitHub
commit d4f6e78c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 26 deletions

View File

@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Worksheet;
use Iterator; use Iterator;
use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Collection\Cells;
/** /**
* @template TKey * @template TKey
@ -18,6 +19,13 @@ abstract class CellIterator implements Iterator
*/ */
protected $worksheet; protected $worksheet;
/**
* Cell Collection to iterate.
*
* @var Cells
*/
protected $cellCollection;
/** /**
* Iterate only existing cells. * Iterate only existing cells.
* *
@ -31,7 +39,7 @@ abstract class CellIterator implements Iterator
public function __destruct() public function __destruct()
{ {
// @phpstan-ignore-next-line // @phpstan-ignore-next-line
$this->worksheet = null; $this->worksheet = $this->cellCollection = null;
} }
/** /**

View File

@ -42,15 +42,16 @@ class ColumnCellIterator extends CellIterator
/** /**
* Create a new row iterator. * Create a new row iterator.
* *
* @param Worksheet $subject The worksheet to iterate over * @param Worksheet $worksheet The worksheet to iterate over
* @param string $columnIndex The column that we want to iterate * @param string $columnIndex The column that we want to iterate
* @param int $startRow The row number at which to start iterating * @param int $startRow The row number at which to start iterating
* @param int $endRow Optionally, the row number at which to stop iterating * @param int $endRow Optionally, the row number at which to stop iterating
*/ */
public function __construct(Worksheet $subject, $columnIndex = 'A', $startRow = 1, $endRow = null) public function __construct(Worksheet $worksheet, $columnIndex = 'A', $startRow = 1, $endRow = null)
{ {
// Set subject // Set subject
$this->worksheet = $subject; $this->worksheet = $worksheet;
$this->cellCollection = $worksheet->getCellCollection();
$this->columnIndex = Coordinate::columnIndexFromString($columnIndex); $this->columnIndex = Coordinate::columnIndexFromString($columnIndex);
$this->resetEnd($endRow); $this->resetEnd($endRow);
$this->resetStart($startRow); $this->resetStart($startRow);
@ -96,7 +97,10 @@ class ColumnCellIterator extends CellIterator
*/ */
public function seek(int $row = 1) public function seek(int $row = 1)
{ {
if ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $row))) { if (
$this->onlyExistingCells &&
(!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->columnIndex) . $row))
) {
throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist'); throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
} }
if (($row < $this->startRow) || ($row > $this->endRow)) { if (($row < $this->startRow) || ($row > $this->endRow)) {
@ -122,8 +126,8 @@ class ColumnCellIterator extends CellIterator
{ {
$cellAddress = Coordinate::stringFromColumnIndex($this->columnIndex) . $this->currentRow; $cellAddress = Coordinate::stringFromColumnIndex($this->columnIndex) . $this->currentRow;
return $this->worksheet->getCellCollection()->has($cellAddress) return $this->cellCollection->has($cellAddress)
? $this->worksheet->getCellCollection()->get($cellAddress) ? $this->cellCollection->get($cellAddress)
: $this->worksheet->createNewCell($cellAddress); : $this->worksheet->createNewCell($cellAddress);
} }
@ -140,12 +144,13 @@ class ColumnCellIterator extends CellIterator
*/ */
public function next(): void public function next(): void
{ {
$columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
do { do {
++$this->currentRow; ++$this->currentRow;
} while ( } while (
($this->onlyExistingCells) && ($this->onlyExistingCells) &&
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->currentRow)) && ($this->currentRow <= $this->endRow) &&
($this->currentRow <= $this->endRow) (!$this->cellCollection->has($columnAddress . $this->currentRow))
); );
} }
@ -154,12 +159,13 @@ class ColumnCellIterator extends CellIterator
*/ */
public function prev(): void public function prev(): void
{ {
$columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
do { do {
--$this->currentRow; --$this->currentRow;
} while ( } while (
($this->onlyExistingCells) && ($this->onlyExistingCells) &&
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->currentRow)) && ($this->currentRow >= $this->startRow) &&
($this->currentRow >= $this->startRow) (!$this->cellCollection->has($columnAddress . $this->currentRow))
); );
} }
@ -177,14 +183,15 @@ class ColumnCellIterator extends CellIterator
protected function adjustForExistingOnlyRange(): void protected function adjustForExistingOnlyRange(): void
{ {
if ($this->onlyExistingCells) { if ($this->onlyExistingCells) {
$columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
while ( while (
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->startRow)) && (!$this->cellCollection->has($columnAddress . $this->startRow)) &&
($this->startRow <= $this->endRow) ($this->startRow <= $this->endRow)
) { ) {
++$this->startRow; ++$this->startRow;
} }
while ( while (
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->endRow)) && (!$this->cellCollection->has($columnAddress . $this->endRow)) &&
($this->endRow >= $this->startRow) ($this->endRow >= $this->startRow)
) { ) {
--$this->endRow; --$this->endRow;

View File

@ -51,6 +51,7 @@ class RowCellIterator extends CellIterator
{ {
// Set subject and row index // Set subject and row index
$this->worksheet = $worksheet; $this->worksheet = $worksheet;
$this->cellCollection = $worksheet->getCellCollection();
$this->rowIndex = $rowIndex; $this->rowIndex = $rowIndex;
$this->resetEnd($endColumn); $this->resetEnd($endColumn);
$this->resetStart($startColumn); $this->resetStart($startColumn);
@ -97,15 +98,14 @@ class RowCellIterator extends CellIterator
*/ */
public function seek(string $column = 'A') public function seek(string $column = 'A')
{ {
$columnx = $column; $columnId = Coordinate::columnIndexFromString($column);
$column = Coordinate::columnIndexFromString($column); if ($this->onlyExistingCells && !($this->cellCollection->has($column . $this->rowIndex))) {
if ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($column, $this->rowIndex))) {
throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist'); throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
} }
if (($column < $this->startColumnIndex) || ($column > $this->endColumnIndex)) { if (($columnId < $this->startColumnIndex) || ($columnId > $this->endColumnIndex)) {
throw new PhpSpreadsheetException("Column $columnx is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})"); throw new PhpSpreadsheetException("Column $column is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})");
} }
$this->currentColumnIndex = $column; $this->currentColumnIndex = $columnId;
return $this; return $this;
} }
@ -125,8 +125,8 @@ class RowCellIterator extends CellIterator
{ {
$cellAddress = Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex; $cellAddress = Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex;
return $this->worksheet->getCellCollection()->has($cellAddress) return $this->cellCollection->has($cellAddress)
? $this->worksheet->getCellCollection()->get($cellAddress) ? $this->cellCollection->get($cellAddress)
: $this->worksheet->createNewCell($cellAddress); : $this->worksheet->createNewCell($cellAddress);
} }
@ -145,7 +145,7 @@ class RowCellIterator extends CellIterator
{ {
do { do {
++$this->currentColumnIndex; ++$this->currentColumnIndex;
} while (($this->onlyExistingCells) && (!$this->worksheet->cellExistsByColumnAndRow($this->currentColumnIndex, $this->rowIndex)) && ($this->currentColumnIndex <= $this->endColumnIndex)); } while (($this->onlyExistingCells) && (!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex)) && ($this->currentColumnIndex <= $this->endColumnIndex));
} }
/** /**
@ -155,7 +155,7 @@ class RowCellIterator extends CellIterator
{ {
do { do {
--$this->currentColumnIndex; --$this->currentColumnIndex;
} while (($this->onlyExistingCells) && (!$this->worksheet->cellExistsByColumnAndRow($this->currentColumnIndex, $this->rowIndex)) && ($this->currentColumnIndex >= $this->startColumnIndex)); } while (($this->onlyExistingCells) && (!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex)) && ($this->currentColumnIndex >= $this->startColumnIndex));
} }
/** /**
@ -180,10 +180,10 @@ class RowCellIterator extends CellIterator
protected function adjustForExistingOnlyRange(): void protected function adjustForExistingOnlyRange(): void
{ {
if ($this->onlyExistingCells) { if ($this->onlyExistingCells) {
while ((!$this->worksheet->cellExistsByColumnAndRow($this->startColumnIndex, $this->rowIndex)) && ($this->startColumnIndex <= $this->endColumnIndex)) { while ((!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->startColumnIndex) . $this->rowIndex)) && ($this->startColumnIndex <= $this->endColumnIndex)) {
++$this->startColumnIndex; ++$this->startColumnIndex;
} }
while ((!$this->worksheet->cellExistsByColumnAndRow($this->endColumnIndex, $this->rowIndex)) && ($this->endColumnIndex >= $this->startColumnIndex)) { while ((!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->endColumnIndex) . $this->rowIndex)) && ($this->endColumnIndex >= $this->startColumnIndex)) {
--$this->endColumnIndex; --$this->endColumnIndex;
} }
} }

View File

@ -112,7 +112,7 @@ class ColumnCellIteratorTest extends TestCase
$iterator->seek(2); $iterator->seek(2);
} }
public function xtestPrevOutOfRange(): void public function testPrevOutOfRange(): void
{ {
$spreadsheet = new Spreadsheet(); $spreadsheet = new Spreadsheet();
$sheet = self::getPopulatedSheet($spreadsheet); $sheet = self::getPopulatedSheet($spreadsheet);