Test reading Xlsx column/row attrs with ReadFilter

When reading an Xlsx file using a ReadFilter it is posible for
`ColumnAndRowAttributes::load()` to (I think) erroneously skip loading
of column or row attributes.

This is because `isFilteredColumn` and `isFilteredRow` will return early
with a true (ie the column or row should be considered filtered and
their attrbutes discarded) at the first false returned from the
ReadFilter. All rows for a column must past the filter for the loop to
return false. I've also created the same test of column widths for row
heights.

 * ColumnWidthTest.php
   Added test with a read filter.
 * RowHeightTest.php
   Mirrored column wdith tests for row height
This commit is contained in:
Alex Wright 2020-12-13 14:45:21 +01:00
parent 8833c239fb
commit 37bf44e9db
2 changed files with 116 additions and 0 deletions

View File

@ -2,6 +2,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Functional; namespace PhpOffice\PhpSpreadsheetTests\Functional;
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
class ColumnWidthTest extends AbstractFunctional class ColumnWidthTest extends AbstractFunctional
@ -31,6 +32,41 @@ class ColumnWidthTest extends AbstractFunctional
$this->assertColumn($reloadedSpreadsheet); $this->assertColumn($reloadedSpreadsheet);
} }
/**
* @dataProvider providerFormats
*
* @param $format
*/
public function testReadColumnWidthWithReadFilter($format): void
{
// Same test with a read filter removing a single row
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
foreach (range(1, 5) as $row) {
$sheet->setCellValue("A{$row}", 'Hello World !');
}
// isFilteredColumn iterates rowAttributes when calling the read filter
$sheet->getRowDimension(5)->setRowHeight(10);
$sheet->getColumnDimension('A')->setWidth(20);
$this->assertColumn($spreadsheet);
// A reader-customeiser closure and ReadFilter implementation that skips rows >4
$readerCustomizer = function ($reader) {
$readFilterStub = $this->createMock(IReadFilter::class);
$readFilterStub->method('readCell')
->willReturnCallback(function ($column, $row, $worksheetName = '') {
return $row <= 4;
});
$reader->setReadFilter($readFilterStub);
};
// Save and reload a filtered set and assert the same width
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $format, $readerCustomizer);
$this->assertColumn($reloadedSpreadsheet);
}
private function assertColumn(Spreadsheet $spreadsheet): void private function assertColumn(Spreadsheet $spreadsheet): void
{ {
$sheet = $spreadsheet->getActiveSheet(); $sheet = $spreadsheet->getActiveSheet();

View File

@ -0,0 +1,80 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Functional;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class RowHeightTest extends AbstractFunctional
{
public function providerFormats()
{
return [
['Xlsx'],
];
}
/**
* @dataProvider providerFormats
*
* @param $format
*/
public function testReadRowHeight($format): void
{
// create new sheet with column width
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'Hello World !');
$sheet->getRowDimension('1')->setRowHeight(20);
$this->assertRow($spreadsheet);
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $format);
$this->assertRow($reloadedSpreadsheet);
}
/**
* @dataProvider providerFormats
*
* @param $format
*/
public function testReadRowHeightWithReadFilter($format): void
{
// Same test with a read filter removing a single row
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
foreach (range(1, 5) as $columnIndex) {
$sheet->setCellValue(Coordinate::stringFromColumnIndex($columnIndex) . '1', 'Hello World !');
}
// isFilteredRow iterates columnAttributes when calling the read filter
$sheet->getColumnDimension('E')->setWidth(64);
$sheet->getRowDimension('1')->setRowHeight(20);
$this->assertRow($spreadsheet);
// A reader-customeiser closure and ReadFilter implementation that skips column 'E'
$readerCustomizer = function ($reader) {
$readFilterStub = $this->createMock(IReadFilter::class);
$readFilterStub->method('readCell')
->willReturnCallback(function ($column, $row, $worksheetName = '') {
return $column !== 'E';
});
$reader->setReadFilter($readFilterStub);
};
// Save and reload a filtered set and assert the same width
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $format, $readerCustomizer);
$this->assertRow($reloadedSpreadsheet);
}
private function assertRow(Spreadsheet $spreadsheet): void
{
$sheet = $spreadsheet->getActiveSheet();
$rowDimensions = $sheet->getRowDimensions();
self::assertArrayHasKey('1', $rowDimensions);
$row = array_shift($rowDimensions);
self::assertEquals(20, $row->getRowHeight());
}
}