Skip to content

Commit 06ea9ea

Browse files
authored
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.
1 parent 95d9cc9 commit 06ea9ea

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

src/PhpSpreadsheet/Reader/Xlsx.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,12 @@ public function load(string $filename, int $flags = 0): Spreadsheet
767767
break;
768768
case 'b':
769769
if (!isset($c->f)) {
770-
$value = self::castToBoolean($c);
770+
if (isset($c->v)) {
771+
$value = self::castToBoolean($c);
772+
} else {
773+
$value = null;
774+
$cellDataType = DATATYPE::TYPE_NULL;
775+
}
771776
} else {
772777
// Formula
773778
$this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean');
@@ -821,10 +826,12 @@ public function load(string $filename, int $flags = 0): Spreadsheet
821826
// Assign value
822827
if ($cellDataType != '') {
823828
// it is possible, that datatype is numeric but with an empty string, which result in an error
824-
if ($cellDataType === DataType::TYPE_NUMERIC && $value === '') {
825-
$cellDataType = DataType::TYPE_STRING;
829+
if ($cellDataType === DataType::TYPE_NUMERIC && ($value === '' || $value === null)) {
830+
$cellDataType = DataType::TYPE_NULL;
831+
}
832+
if ($cellDataType !== DataType::TYPE_NULL) {
833+
$cell->setValueExplicit($value, $cellDataType);
826834
}
827-
$cell->setValueExplicit($value, $cellDataType);
828835
} else {
829836
$cell->setValue($value);
830837
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
4+
5+
use PhpOffice\PhpSpreadsheet\IOFactory;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class Issue2488Test extends TestCase
9+
{
10+
/**
11+
* @var string
12+
*/
13+
private static $testbook = 'tests/data/Reader/XLSX/issue.2488.xlsx';
14+
15+
public function testPreliminaries(): void
16+
{
17+
$file = 'zip://';
18+
$file .= self::$testbook;
19+
$file .= '#xl/worksheets/sheet1.xml';
20+
$data = file_get_contents($file);
21+
// confirm that file contains expected namespaced xml tag
22+
if ($data === false) {
23+
self::fail('Unable to read file');
24+
} else {
25+
self::assertStringContainsString('<c r="E1" t="n" />', $data);
26+
self::assertStringContainsString('<c r="E2" t="s" />', $data);
27+
self::assertStringContainsString('<c r="D3" t="b" />', $data);
28+
}
29+
}
30+
31+
public function testIssue2450(): void
32+
{
33+
// Cell explicitly typed as numeric but without value.
34+
$filename = self::$testbook;
35+
$reader = IOFactory::createReader('Xlsx');
36+
$spreadsheet = $reader->load($filename);
37+
$sheet = $spreadsheet->getActiveSheet();
38+
// E1 and D3 are numeric/boolean without value.
39+
// So is E2, but I don't see a practical difference
40+
// between null string and null in that case.
41+
$expected = [
42+
[1, 2, 3, 0, null, -1, -2, -3],
43+
['a', 'b', 'c', 'xxx', '', 'd', 'e', 'f'],
44+
[false, false, false, null, true, true, true, true],
45+
];
46+
self::assertSame($expected, $sheet->toArray());
47+
48+
$spreadsheet->disconnectWorksheets();
49+
}
50+
}
7.51 KB
Binary file not shown.

0 commit comments

Comments
 (0)