Allow Csv Reader to Store Null String in Spreadsheet (#2842)

Fix #2840 (and also #2839 but that's Q&A, not an issue). Csv Reader does not populate cells which contain null string. This PR provides an option for the reader to store null strings as it does with any other string.
This commit is contained in:
oleibman 2022-05-21 07:21:14 -07:00 committed by GitHub
parent ef031e74e1
commit 567b9601b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 6 deletions

View File

@ -449,8 +449,7 @@ $spreadsheet = $reader->loadSpreadsheetFromString($data);
#### Setting CSV options
Often, CSV files are not really "comma separated", or use semicolon (`;`)
as a separator. You can instruct
`\PhpOffice\PhpSpreadsheet\Reader\Csv` some options before reading a CSV
as a separator. You can set some options before reading a CSV
file.
The separator will be auto-detected, so in most cases it should not be necessary
@ -506,6 +505,12 @@ $reader->setSheetIndex(0);
$spreadsheet = $reader->load('sample.csv');
```
The CSV reader will normally not load null strings into the spreadsheet.
To load them:
```php
$reader->setPreserveNullString(true);
```
Finally, you can set a callback to be invoked when the constructor is executed,
either through `new Csv()` or `IOFactory::load`,
and have that callback set the customizable attributes to whatever
@ -584,8 +589,7 @@ $writer->save("05featuredemo.csv");
#### Setting CSV options
Often, CSV files are not really "comma separated", or use semicolon (`;`)
as a separator. You can instruct
`\PhpOffice\PhpSpreadsheet\Writer\Csv` some options before writing a CSV
as a separator. You can set some options before writing a CSV
file:
```php

View File

@ -103,6 +103,9 @@ class Csv extends BaseReader
*/
protected $preserveNumericFormatting = false;
/** @var bool */
private $preserveNullString = false;
/**
* Create a new CSV Reader instance.
*/
@ -300,9 +303,11 @@ class Csv extends BaseReader
}
}
public function setTestAutoDetect(bool $value): void
public function setTestAutoDetect(bool $value): self
{
$this->testAutodetect = $value;
return $this;
}
private function setAutoDetect(?string $value): ?string
@ -390,7 +395,7 @@ class Csv extends BaseReader
foreach ($rowData as $rowDatum) {
$this->convertBoolean($rowDatum, $preserveBooleanString);
$numberFormatMask = $this->convertFormattedNumber($rowDatum);
if ($rowDatum !== '' && $this->readFilter->readCell($columnLetter, $currentRow)) {
if (($rowDatum !== '' || $this->preserveNullString) && $this->readFilter->readCell($columnLetter, $currentRow)) {
if ($this->contiguous) {
if ($noOutputYet) {
$noOutputYet = false;
@ -625,4 +630,16 @@ class Csv extends BaseReader
return ($encoding === '') ? $dflt : $encoding;
}
public function setPreserveNullString(bool $value): self
{
$this->preserveNullString = $value;
return $this;
}
public function getPreserveNullString(): bool
{
return $this->preserveNullString;
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use PHPUnit\Framework\TestCase;
class CsvIssue2840Test extends TestCase
{
public function testNullStringIgnore(): void
{
$reader = new Csv();
self::assertFalse($reader->getPreserveNullString());
$inputData = <<<EOF
john,,doe,,
mary,,jane,,
EOF;
$expected = [
['john', null, 'doe'],
['mary', null, 'jane'],
];
$spreadsheet = $reader->loadSpreadsheetFromString($inputData);
$sheet = $spreadsheet->getActiveSheet();
self::assertSame($expected, $sheet->toArray());
$spreadsheet->disconnectWorksheets();
}
public function testNullStringLoad(): void
{
$reader = new Csv();
$reader->setPreserveNullString(true);
$inputData = <<<EOF
john,,doe,,
mary,,jane,,
EOF;
$expected = [
['john', '', 'doe', '', ''],
['mary', '', 'jane', '', ''],
];
$spreadsheet = $reader->loadSpreadsheetFromString($inputData);
$sheet = $spreadsheet->getActiveSheet();
self::assertSame($expected, $sheet->toArray());
$spreadsheet->disconnectWorksheets();
}
}