Modify XLSX RW to keep decimal for floats with a zero decimal part
Prior to 1.10, all numeric values where read as floats. In 1.10 numeric values are read using 0 + x, which relies on PHP type juggling rules. As a result, float(0.0) is written as string('0'), then read back as int(0). This fix causes the writer to retain the the decimal for float values such that a reader can differentiate floats from ints. Closes #1262
This commit is contained in:
parent
9552172b85
commit
cf30c2a824
|
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
|
||||
- FLOOR() function accept negative number and negative significance [#1245](https://github.com/PHPOffice/PhpSpreadsheet/pull/1245)
|
||||
- Correct column style even when using rowspan [#1249](https://github.com/PHPOffice/PhpSpreadsheet/pull/1249)
|
||||
- XLSX reader/writer keep decimal for floats with a zero decimal part [#1262](https://github.com/PHPOffice/PhpSpreadsheet/pull/1262)
|
||||
|
||||
## [1.10.0] - 2019-11-18
|
||||
|
||||
|
|
|
@ -729,15 +729,6 @@ class Xlsx extends BaseReader
|
|||
|
||||
// read empty cells or the cells are not empty
|
||||
if ($this->readEmptyCells || ($value !== null && $value !== '')) {
|
||||
// Check for numeric values
|
||||
if (is_numeric($value) && $cellDataType != 's') {
|
||||
if ($value == (int) $value) {
|
||||
$value = (int) $value;
|
||||
} elseif ($value == (float) $value) {
|
||||
$value = (float) $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Rich text?
|
||||
if ($value instanceof RichText && $this->readDataOnly) {
|
||||
$value = $value->getPlainText();
|
||||
|
|
|
@ -1135,6 +1135,13 @@ class Worksheet extends WriterPart
|
|||
|
||||
break;
|
||||
case 'n': // Numeric
|
||||
//force a decimal to be written if the type is float
|
||||
if (is_float($cellValue)) {
|
||||
$cellValue = (string) $cellValue;
|
||||
if (strpos($cellValue, '.') === false) {
|
||||
$cellValue = $cellValue . '.0';
|
||||
}
|
||||
}
|
||||
// force point as decimal separator in case current locale uses comma
|
||||
$objWriter->writeElement('v', str_replace(',', '.', $cellValue));
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as Reader;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as Writer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FloatsRetainedTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerIntyFloatsRetainedByWriter
|
||||
*
|
||||
* @param float|int $value
|
||||
*/
|
||||
public function testIntyFloatsRetainedByWriter($value)
|
||||
{
|
||||
$outputFilename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
|
||||
Settings::setLibXmlLoaderOptions(null);
|
||||
$sheet = new Spreadsheet();
|
||||
$sheet->getActiveSheet()->getCell('A1')->setValue($value);
|
||||
|
||||
$writer = new Writer($sheet);
|
||||
$writer->save($outputFilename);
|
||||
|
||||
$reader = new Reader();
|
||||
$sheet = $reader->load($outputFilename);
|
||||
|
||||
$this->assertSame($value, $sheet->getActiveSheet()->getCell('A1')->getValue());
|
||||
}
|
||||
|
||||
public function providerIntyFloatsRetainedByWriter()
|
||||
{
|
||||
return [
|
||||
[-1.0],
|
||||
[-1],
|
||||
[0.0],
|
||||
[0],
|
||||
[1.0],
|
||||
[1],
|
||||
[1e-3],
|
||||
[1.3e-10],
|
||||
[1e10],
|
||||
[3.00000000000000000001],
|
||||
[99999999999999999],
|
||||
[99999999999999999.0],
|
||||
[999999999999999999999999999999999999999999],
|
||||
[999999999999999999999999999999999999999999.0],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue