New functionality to allow checking whether a row or column is "empty", with flags to allow variation in the definition of "empty"
This commit is contained in:
parent
5608e05eda
commit
b62de98bf7
|
|
@ -18,6 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850)
|
- Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850)
|
||||||
- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792)
|
- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792)
|
||||||
- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842)
|
- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842)
|
||||||
|
- Provide new Worksheet methods to identify if a row or column is "empty", making allowance for different definitions of "empty":
|
||||||
|
- Treat rows/columns containing no cell records as empty (default)
|
||||||
|
- Treat cells containing a null value as empty
|
||||||
|
- Treat cells containing an empty string as empty
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3655,11 +3655,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Worksheet/CellIterator.php
|
path: src/PhpSpreadsheet/Worksheet/CellIterator.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Column\\:\\:\\$parent \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Worksheet/Column.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3685,11 +3680,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Worksheet/PageSetup.php
|
path: src/PhpSpreadsheet/Worksheet/PageSetup.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Row\\:\\:\\$worksheet \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Worksheet/Row.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\SheetView\\:\\:\\$sheetViewTypes has no type specified\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\SheetView\\:\\:\\$sheetViewTypes has no type specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@ use PhpOffice\PhpSpreadsheet\Collection\Cells;
|
||||||
*/
|
*/
|
||||||
abstract class CellIterator implements Iterator
|
abstract class CellIterator implements Iterator
|
||||||
{
|
{
|
||||||
|
public const TREAT_NULL_VALUE_AS_EMPTY_CELL = 1;
|
||||||
|
|
||||||
|
public const TREAT_EMPTY_STRING_AS_EMPTY_CELL = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worksheet to iterate.
|
* Worksheet to iterate.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class Column
|
||||||
*
|
*
|
||||||
* @var Worksheet
|
* @var Worksheet
|
||||||
*/
|
*/
|
||||||
private $parent;
|
private $worksheet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column index.
|
* Column index.
|
||||||
|
|
@ -23,10 +23,10 @@ class Column
|
||||||
*
|
*
|
||||||
* @param string $columnIndex
|
* @param string $columnIndex
|
||||||
*/
|
*/
|
||||||
public function __construct(?Worksheet $parent = null, $columnIndex = 'A')
|
public function __construct(Worksheet $worksheet, $columnIndex = 'A')
|
||||||
{
|
{
|
||||||
// Set parent and column index
|
// Set parent and column index
|
||||||
$this->parent = $parent;
|
$this->worksheet = $worksheet;
|
||||||
$this->columnIndex = $columnIndex;
|
$this->columnIndex = $columnIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ class Column
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
// @phpstan-ignore-next-line
|
// @phpstan-ignore-next-line
|
||||||
$this->parent = null;
|
$this->worksheet = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,6 +57,53 @@ class Column
|
||||||
*/
|
*/
|
||||||
public function getCellIterator($startRow = 1, $endRow = null)
|
public function getCellIterator($startRow = 1, $endRow = null)
|
||||||
{
|
{
|
||||||
return new ColumnCellIterator($this->parent, $this->columnIndex, $startRow, $endRow);
|
return new ColumnCellIterator($this->worksheet, $this->columnIndex, $startRow, $endRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the column contains no cells. By default, this means that no cell records exist in the
|
||||||
|
* collection for this column. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the column will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the column will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the column
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmpty(int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
$nullValueCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
$emptyStringCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
$cellIterator = $this->getCellIterator();
|
||||||
|
$cellIterator->setIterateOnlyExistingCells(true);
|
||||||
|
foreach ($cellIterator as $cell) {
|
||||||
|
$value = $cell->getValue();
|
||||||
|
if ($value === null && $nullValueCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($value === '' && $emptyStringCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns bound worksheet.
|
||||||
|
*/
|
||||||
|
public function getWorksheet(): Worksheet
|
||||||
|
{
|
||||||
|
return $this->worksheet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class Row
|
||||||
*
|
*
|
||||||
* @param int $rowIndex
|
* @param int $rowIndex
|
||||||
*/
|
*/
|
||||||
public function __construct(?Worksheet $worksheet = null, $rowIndex = 1)
|
public function __construct(Worksheet $worksheet, $rowIndex = 1)
|
||||||
{
|
{
|
||||||
// Set parent and row index
|
// Set parent and row index
|
||||||
$this->worksheet = $worksheet;
|
$this->worksheet = $worksheet;
|
||||||
|
|
@ -59,6 +59,45 @@ class Row
|
||||||
return new RowCellIterator($this->worksheet, $this->rowIndex, $startColumn, $endColumn);
|
return new RowCellIterator($this->worksheet, $this->rowIndex, $startColumn, $endColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the row contains no cells. By default, this means that no cell records exist in the
|
||||||
|
* collection for this row. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the row will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the row will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the row
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmpty(int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
$nullValueCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
$emptyStringCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
$cellIterator = $this->getCellIterator();
|
||||||
|
$cellIterator->setIterateOnlyExistingCells(true);
|
||||||
|
foreach ($cellIterator as $cell) {
|
||||||
|
$value = $cell->getValue();
|
||||||
|
if ($value === null && $nullValueCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($value === '' && $emptyStringCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns bound worksheet.
|
* Returns bound worksheet.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -3232,6 +3232,66 @@ class Worksheet implements IComparable
|
||||||
return clone $this;
|
return clone $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the specified row contains no cells. By default, this means that no cell records
|
||||||
|
* exist in the collection for this row. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the row will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the row will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the row
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmptyRow(int $rowId, int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$iterator = new RowIterator($this, $rowId, $rowId);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $row->isEmpty($definitionOfEmptyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the specified column contains no cells. By default, this means that no cell records
|
||||||
|
* exist in the collection for this column. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the column will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the column will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the column
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmptyColumn(string $columnId, int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$iterator = new ColumnIterator($this, $columnId, $columnId);
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$column = $iterator->current();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $column->isEmpty($definitionOfEmptyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\ColumnIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ColumnIteratorEmptyTest extends TestCase
|
||||||
|
{
|
||||||
|
private static function getPopulatedSheet(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('D2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('E2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('E3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('F2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('F3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('H3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H4', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnBasic
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumn(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty();
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnBasic(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', false],
|
||||||
|
['D', false],
|
||||||
|
['E', false],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnNullAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumnWithNull(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnNullAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', true],
|
||||||
|
['D', false],
|
||||||
|
['E', false],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumnWithEmptyString(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', false],
|
||||||
|
['D', true],
|
||||||
|
['E', false],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnNullAndEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumnWithNullAndEmptyString(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(
|
||||||
|
CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnNullAndEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', true],
|
||||||
|
['D', true],
|
||||||
|
['E', true],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\RowIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class RowIteratorEmptyTest extends TestCase
|
||||||
|
{
|
||||||
|
private static function getPopulatedSheet(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B3', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('B4', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B5', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C5', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B6', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C6', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B7', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C7', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B8', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C8', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('D8', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowBasic
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRow(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty();
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowBasic(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, false],
|
||||||
|
[4, false],
|
||||||
|
[5, false],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowNullAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRowWithNull(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowNullAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, true],
|
||||||
|
[4, false],
|
||||||
|
[5, false],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRowWithEmptyString(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, false],
|
||||||
|
[4, true],
|
||||||
|
[5, false],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowNullAndEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRowWithNullAndEmptyString(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(
|
||||||
|
CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowNullAndEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, true],
|
||||||
|
[4, true],
|
||||||
|
[5, true],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
|
@ -405,4 +407,100 @@ class WorksheetTest extends TestCase
|
||||||
self::assertSame($expectedData, $worksheet->toArray());
|
self::assertSame($expectedData, $worksheet->toArray());
|
||||||
self::assertSame($expectedHighestRow, $worksheet->getHighestRow());
|
self::assertSame($expectedHighestRow, $worksheet->getHighestRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getPopulatedSheetForEmptyRowTest(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B3', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('B4', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B5', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C5', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B6', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C6', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B7', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C7', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B8', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C8', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('D8', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getPopulatedSheetForEmptyColumnTest(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('D2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('E2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('E3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('F2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('F3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('H3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H4', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowProvider
|
||||||
|
*/
|
||||||
|
public function testIsEmptyRow(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheetForEmptyRowTest($spreadsheet);
|
||||||
|
|
||||||
|
$isEmpty = $sheet->isEmptyRow($rowId, CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, true],
|
||||||
|
[4, true],
|
||||||
|
[5, true],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnProvider
|
||||||
|
*/
|
||||||
|
public function testIsEmptyColumn(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheetForEmptyColumnTest($spreadsheet);
|
||||||
|
|
||||||
|
$isEmpty = $sheet->isEmptyColumn($columnId, CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', true],
|
||||||
|
['D', true],
|
||||||
|
['E', true],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue