commit
6c57125c0c
@ -20,6 +20,7 @@ class RowIterator implements IteratorInterface
|
|||||||
const XML_NODE_TABLE = 'table:table';
|
const XML_NODE_TABLE = 'table:table';
|
||||||
const XML_NODE_ROW = 'table:table-row';
|
const XML_NODE_ROW = 'table:table-row';
|
||||||
const XML_NODE_CELL = 'table:table-cell';
|
const XML_NODE_CELL = 'table:table-cell';
|
||||||
|
const MAX_COLUMNS_EXCEL = 16384;
|
||||||
|
|
||||||
/** Definition of XML attribute used to parse data */
|
/** Definition of XML attribute used to parse data */
|
||||||
const XML_ATTRIBUTE_NUM_COLUMNS_REPEATED = 'table:number-columns-repeated';
|
const XML_ATTRIBUTE_NUM_COLUMNS_REPEATED = 'table:number-columns-repeated';
|
||||||
@ -127,22 +128,23 @@ class RowIterator implements IteratorInterface
|
|||||||
|
|
||||||
} else if ($this->xmlReader->isPositionedOnEndingNode(self::XML_NODE_ROW)) {
|
} else if ($this->xmlReader->isPositionedOnEndingNode(self::XML_NODE_ROW)) {
|
||||||
// End of the row description
|
// End of the row description
|
||||||
$isEmptyRow = ($numCellsRead <= 1 && empty($cellValue));
|
$isEmptyRow = ($numCellsRead <= 1 && $this->isEmptyCellValue($cellValue));
|
||||||
if ($isEmptyRow) {
|
if ($isEmptyRow) {
|
||||||
// skip empty rows
|
// skip empty rows
|
||||||
$this->next();
|
$this->next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only add value if the last read cell is not empty or does not need to repeat cell values.
|
// Only add the value if the last read cell is not a trailing empty cell repeater in Excel.
|
||||||
|
// The current count of read columns is determined by counting the values in $rowData.
|
||||||
// This is to avoid creating a lot of empty cells, as Excel adds a last empty "<table:table-cell>"
|
// This is to avoid creating a lot of empty cells, as Excel adds a last empty "<table:table-cell>"
|
||||||
// with a number-columns-repeated value equals to the number of (supported columns - used columns).
|
// with a number-columns-repeated value equals to the number of (supported columns - used columns).
|
||||||
// In Excel, the number of supported columns is 16384, but we don't want to returns rows with always 16384 cells.
|
// In Excel, the number of supported columns is 16384, but we don't want to returns rows with
|
||||||
if (!empty($cellValue) || $numColumnsRepeated === 1) {
|
// always 16384 cells.
|
||||||
|
if ((count($rowData) + $numColumnsRepeated) !== self::MAX_COLUMNS_EXCEL) {
|
||||||
for ($i = 0; $i < $numColumnsRepeated; $i++) {
|
for ($i = 0; $i < $numColumnsRepeated; $i++) {
|
||||||
$rowData[] = $cellValue;
|
$rowData[] = $cellValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->numReadRows++;
|
$this->numReadRows++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -181,6 +183,17 @@ class RowIterator implements IteratorInterface
|
|||||||
return $this->cellValueFormatter->extractAndFormatNodeValue($node);
|
return $this->cellValueFormatter->extractAndFormatNodeValue($node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* empty() replacement that honours 0 as a valid value
|
||||||
|
*
|
||||||
|
* @param $value The cell value
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isEmptyCellValue($value)
|
||||||
|
{
|
||||||
|
return (!isset($value) || trim($value) === '');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current element, from the buffer.
|
* Return the current element, from the buffer.
|
||||||
* @link http://php.net/manual/en/iterator.current.php
|
* @link http://php.net/manual/en/iterator.current.php
|
||||||
|
@ -343,6 +343,38 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals($expectedRows, $allRows);
|
$this->assertEquals($expectedRows, $allRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/box/spout/issues/184
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldInludeRowsWithZerosOnly()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_zeros_in_row.csv');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['A', 'B', 'C'],
|
||||||
|
['1', '2', '3'],
|
||||||
|
['0', '0', '0']
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows, 'There should be only 3 rows, because zeros (0) are valid values');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/box/spout/issues/184
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldCreateOutputEmptyCellPreserved()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_empty_cells.csv');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['A', 'B', 'C'],
|
||||||
|
['0', '', ''],
|
||||||
|
['1', '1', '']
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows, 'There should be 3 rows, with equal length');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @param string|void $fieldDelimiter
|
* @param string|void $fieldDelimiter
|
||||||
|
@ -387,6 +387,38 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$reader->open('php://memory');
|
$reader->open('php://memory');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/box/spout/issues/184
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldInludeRowsWithZerosOnly()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_zeros_in_row.ods');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['A', 'B', 'C'],
|
||||||
|
['1', '2', '3'],
|
||||||
|
['0', '0', '0']
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows, 'There should be only 3 rows, because zeros (0) are valid values');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/box/spout/issues/184
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldCreateOutputEmptyCellPreserved()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_empty_cells.ods');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['A', 'B', 'C'],
|
||||||
|
['0', '', ''],
|
||||||
|
['1', '1', '']
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows, 'There should be 3 rows, with equal length');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @return array All the read rows the given file
|
* @return array All the read rows the given file
|
||||||
|
@ -428,6 +428,39 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$reader->open('php://memory');
|
$reader->open('php://memory');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/box/spout/issues/184
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldInludeRowsWithZerosOnly()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_zeros_in_row.xlsx');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['A', 'B', 'C'],
|
||||||
|
['1', '2', '3'],
|
||||||
|
['0', '0', '0']
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows, 'There should be only 3 rows, because zeros (0) are valid values');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/box/spout/issues/184
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testReadShouldCreateOutputEmptyCellPreserved()
|
||||||
|
{
|
||||||
|
$allRows = $this->getAllRowsForFile('sheet_with_empty_cells.xlsx');
|
||||||
|
|
||||||
|
$expectedRows = [
|
||||||
|
['A', 'B', 'C'],
|
||||||
|
['0', '', ''],
|
||||||
|
['1', '1', '']
|
||||||
|
];
|
||||||
|
$this->assertEquals($expectedRows, $allRows, 'There should be 3 rows, with equal length');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @return array All the read rows the given file
|
* @return array All the read rows the given file
|
||||||
|
3
tests/resources/csv/sheet_with_empty_cells.csv
Normal file
3
tests/resources/csv/sheet_with_empty_cells.csv
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"A","B","C"
|
||||||
|
0,,
|
||||||
|
1,1,
|
|
3
tests/resources/csv/sheet_with_zeros_in_row.csv
Normal file
3
tests/resources/csv/sheet_with_zeros_in_row.csv
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"A","B","C"
|
||||||
|
1,2,3
|
||||||
|
0,0,0
|
|
BIN
tests/resources/ods/sheet_with_empty_cells.ods
Normal file
BIN
tests/resources/ods/sheet_with_empty_cells.ods
Normal file
Binary file not shown.
BIN
tests/resources/ods/sheet_with_zeros_in_row.ods
Normal file
BIN
tests/resources/ods/sheet_with_zeros_in_row.ods
Normal file
Binary file not shown.
BIN
tests/resources/xlsx/sheet_with_empty_cells.xlsx
Normal file
BIN
tests/resources/xlsx/sheet_with_empty_cells.xlsx
Normal file
Binary file not shown.
BIN
tests/resources/xlsx/sheet_with_zeros_in_row.xlsx
Normal file
BIN
tests/resources/xlsx/sheet_with_zeros_in_row.xlsx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user