Xlsx Reader Cell DataType Numeric or Boolean Without Value (#2489)

Fix #2488. When Excel sees this situation, it leaves the value of the cell as null rather than casting to the specified DataType. It doesn't really make sense to change setValueExplicit to adopt this convention; it should be sufficient to recognize the situation in the Reader and act there. The same sort of situation might apply to strings, but I don't see any practical difference between null string and null even if so.
This commit is contained in:
oleibman 2022-01-16 21:19:09 -08:00 committed by GitHub
parent 95d9cc965d
commit 06ea9ead2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 4 deletions

View File

@ -767,7 +767,12 @@ class Xlsx extends BaseReader
break;
case 'b':
if (!isset($c->f)) {
$value = self::castToBoolean($c);
if (isset($c->v)) {
$value = self::castToBoolean($c);
} else {
$value = null;
$cellDataType = DATATYPE::TYPE_NULL;
}
} else {
// Formula
$this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean');
@ -821,10 +826,12 @@ class Xlsx extends BaseReader
// Assign value
if ($cellDataType != '') {
// it is possible, that datatype is numeric but with an empty string, which result in an error
if ($cellDataType === DataType::TYPE_NUMERIC && $value === '') {
$cellDataType = DataType::TYPE_STRING;
if ($cellDataType === DataType::TYPE_NUMERIC && ($value === '' || $value === null)) {
$cellDataType = DataType::TYPE_NULL;
}
if ($cellDataType !== DataType::TYPE_NULL) {
$cell->setValueExplicit($value, $cellDataType);
}
$cell->setValueExplicit($value, $cellDataType);
} else {
$cell->setValue($value);
}

View File

@ -0,0 +1,50 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PHPUnit\Framework\TestCase;
class Issue2488Test extends TestCase
{
/**
* @var string
*/
private static $testbook = 'tests/data/Reader/XLSX/issue.2488.xlsx';
public function testPreliminaries(): void
{
$file = 'zip://';
$file .= self::$testbook;
$file .= '#xl/worksheets/sheet1.xml';
$data = file_get_contents($file);
// confirm that file contains expected namespaced xml tag
if ($data === false) {
self::fail('Unable to read file');
} else {
self::assertStringContainsString('<c r="E1" t="n" />', $data);
self::assertStringContainsString('<c r="E2" t="s" />', $data);
self::assertStringContainsString('<c r="D3" t="b" />', $data);
}
}
public function testIssue2450(): void
{
// Cell explicitly typed as numeric but without value.
$filename = self::$testbook;
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($filename);
$sheet = $spreadsheet->getActiveSheet();
// E1 and D3 are numeric/boolean without value.
// So is E2, but I don't see a practical difference
// between null string and null in that case.
$expected = [
[1, 2, 3, 0, null, -1, -2, -3],
['a', 'b', 'c', 'xxx', '', 'd', 'e', 'f'],
[false, false, false, null, true, true, true, true],
];
self::assertSame($expected, $sheet->toArray());
$spreadsheet->disconnectWorksheets();
}
}

Binary file not shown.