Skip to content

Commit 52f5b24

Browse files
authored
Inconsistency Between Actual and Declared Type - Minor Break (#3715)
* Inconsistency Between Actual and Declared Type - Minor Break Fix #3711. User set a cell value to float (implicitly by default value binder), then used `setDataType` to change its type to string. This caused a problem for Xlsx Writer, which uses the string cell values as an index into a Shared String array. However, as the cell actually contained a floating point value, Php treated it as an integer index; such a treatment is both deprecated, and leads to invalid values in the spreadsheet. The use case for `setDataType` is not strong. The user always has the option to use `setValueExplicit` if the type is important. Setting a type afterwards, i.e. irrespective of the value, seems like a peculiar action. Indeed, there are no tests whatever for such use in the unit test suite. There are two possible approaches to fixing this problem. The first is to add casts to the 3 or 4 places in Writer Xlsx which might be affected by this problem (hoping that you've found them all and realizing that similar changes might be needed for other Writers). The second is to change `setDataType` to call `setValueExplicit` using the current value of the cell, thereby possibly changing the cell value. I have gone with the second option - it seems like a much more logical approach, and guarantees that the content of the cell will always be consistent with its declared type. It is, however, a breaking change; if, for example, you have a cell with a string or numeric value and specify `boolean` to `setDataType`, the cell's value will change to `true` or `false` with no way to get back to the original. * Strict Types for New Tests Consistent with work being done in PR #3718. * Improve Test Better match to original issue. * Typo
1 parent 0d1c9e4 commit 52f5b24

File tree

3 files changed

+78
-5
lines changed

3 files changed

+78
-5
lines changed

src/PhpSpreadsheet/Cell/Cell.php

+2-5
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,9 @@ public function getDataType(): string
457457
*/
458458
public function setDataType($dataType): self
459459
{
460-
if ($dataType == DataType::TYPE_STRING2) {
461-
$dataType = DataType::TYPE_STRING;
462-
}
463-
$this->dataType = $dataType;
460+
$this->setValueExplicit($this->value, $dataType);
464461

465-
return $this->updateInCollection();
462+
return $this;
466463
}
467464

468465
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Cell;
6+
7+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8+
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
9+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
10+
use PHPUnit\Framework\TestCase;
11+
12+
class DataType2Test extends TestCase
13+
{
14+
public function testSetDataType(): void
15+
{
16+
$spreadsheet = new Spreadsheet();
17+
$sheet = $spreadsheet->getActiveSheet();
18+
$sheet->getCell('A1')->setValue(28.1);
19+
self::assertSame(28.1, $sheet->getCell('A1')->getValue());
20+
self::assertSame('28.1', (string) $sheet->getCell('A1'));
21+
$sheet->getCell('A1')->setDataType(DataType::TYPE_STRING);
22+
self::assertSame('28.1', $sheet->getCell('A1')->getValue());
23+
$sheet->getCell('A1')->setDataType(DataType::TYPE_NUMERIC);
24+
self::assertSame(28.1, $sheet->getCell('A1')->getValue());
25+
$sheet->getCell('A1')->setDataType(DataType::TYPE_STRING2);
26+
self::assertSame('28.1', $sheet->getCell('A1')->getValue());
27+
$sheet->getCell('A1')->setDataType(DataType::TYPE_INLINE);
28+
self::assertSame('28.1', $sheet->getCell('A1')->getValue());
29+
$sheet->getCell('A1')->setDataType(DataType::TYPE_BOOL);
30+
self::assertTrue($sheet->getCell('A1')->getValue());
31+
$sheet->getCell('A1')->setDataType(DataType::TYPE_NUMERIC);
32+
self::assertSame(1, $sheet->getCell('A1')->getValue());
33+
34+
$sheet->getCell('A2')->setValue('X');
35+
36+
try {
37+
$sheet->getCell('A2')->setDataType(DataType::TYPE_NUMERIC);
38+
} catch (PhpSpreadsheetException $e) {
39+
self::assertSame('Invalid numeric value for datatype Numeric', $e->getMessage());
40+
}
41+
42+
$spreadsheet->disconnectWorksheets();
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
9+
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
10+
11+
class Issue3711Test extends AbstractFunctional
12+
{
13+
public function testIssue3711(): void
14+
{
15+
// Issue 3711 - float being used as index in StringTable.
16+
$spreadsheet = new Spreadsheet();
17+
$sheet = $spreadsheet->getActiveSheet();
18+
$sheet->getCell('A1')->setValue('21.5');
19+
self::assertSame(21.5, $sheet->getCell('A1')->getValue());
20+
$sheet->getCell('A1')->setDataType(DataType::TYPE_STRING);
21+
$sheet->getCell('A2')->setValue('21');
22+
self::assertSame(21, $sheet->getCell('A2')->getValue());
23+
$sheet->getCell('A2')->setDataType(DataType::TYPE_STRING);
24+
25+
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
26+
$spreadsheet->disconnectWorksheets();
27+
$rsheet = $reloadedSpreadsheet->getActiveSheet();
28+
self::assertSame('21.5', $rsheet->getCell('A1')->getValue());
29+
self::assertSame('21', $rsheet->getCell('A2')->getValue());
30+
$reloadedSpreadsheet->disconnectWorksheets();
31+
}
32+
}

0 commit comments

Comments
 (0)