mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-08-30 03:59:11 +00:00
Strings That Look Like Huge Floating Point Numbers
Fix #4776. DefaultValueBinder treats strings that look like scientific notation as floats. However, if Php evaluates them as `INF`, this can cause problems for Excel. A one-line change to DefaultValueBinder avoids this situation. Tests are added for DefaultValueBinder, and also for StringValueBinder and AdvancedValueBinder, although those extend DefaultValueBinder and needed no code changes.
This commit is contained in:
@@ -107,7 +107,7 @@ class DefaultValueBinder implements IValueBinder
|
||||
return DataType::TYPE_STRING;
|
||||
}
|
||||
}
|
||||
if (!is_numeric($value)) {
|
||||
if (!is_numeric($value) || !is_finite((float) $value)) {
|
||||
return DataType::TYPE_STRING;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AdvancedValueBinderTest extends TestCase
|
||||
@@ -84,7 +85,7 @@ class AdvancedValueBinderTest extends TestCase
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('currencyProvider')]
|
||||
#[DataProvider('currencyProvider')]
|
||||
public function testCurrency(string $value, float $valueBinded, string $thousandsSeparator, string $decimalSeparator, string $currencyCode): void
|
||||
{
|
||||
StringHelper::setCurrencyCode($currencyCode);
|
||||
@@ -119,7 +120,7 @@ class AdvancedValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('fractionProvider')]
|
||||
#[DataProvider('fractionProvider')]
|
||||
public function testFractions(mixed $value, mixed $valueBinded): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
@@ -156,7 +157,7 @@ class AdvancedValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('percentageProvider')]
|
||||
#[DataProvider('percentageProvider')]
|
||||
public function testPercentages(mixed $value, mixed $valueBinded): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
@@ -181,7 +182,7 @@ class AdvancedValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('timeProvider')]
|
||||
#[DataProvider('timeProvider')]
|
||||
public function testTimes(mixed $value, mixed $valueBinded): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
@@ -204,7 +205,7 @@ class AdvancedValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('stringProvider')]
|
||||
#[DataProvider('stringProvider')]
|
||||
public function testStringWrapping(string $value): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
@@ -224,7 +225,7 @@ class AdvancedValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('formulaProvider')]
|
||||
#[DataProvider('formulaProvider')]
|
||||
public function testFormula(string $value, string $dataType): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
@@ -248,4 +249,29 @@ class AdvancedValueBinderTest extends TestCase
|
||||
'issue 1310' => ['======', DataType::TYPE_STRING],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('nativeProvider')]
|
||||
public function testNative(mixed $value, mixed $expected = null): void
|
||||
{
|
||||
$expected ??= $value;
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getCell('A1')->setValue($value);
|
||||
self::assertSame($expected, $sheet->getCell('A1')->getValue());
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
public static function nativeProvider(): array
|
||||
{
|
||||
return [
|
||||
'int' => [2],
|
||||
'float' => [3.0],
|
||||
'numeric string' => ['15', 15],
|
||||
'scientific notation' => ['2.5E1', 25.0],
|
||||
'issue4766 large exponent' => ['4E433'],
|
||||
'issue4766 large negative exponent' => ['4E-433', 0.0],
|
||||
'boolean' => [false],
|
||||
'string' => ['xyz'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,12 @@ use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DefaultValueBinderTest extends TestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('binderProvider')]
|
||||
#[DataProvider('binderProvider')]
|
||||
public function testBindValue(null|string|bool|int|float|DateTime|DateTimeImmutable $value): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
@@ -70,7 +71,7 @@ class DefaultValueBinderTest extends TestCase
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataTypeForValue')]
|
||||
#[DataProvider('providerDataTypeForValue')]
|
||||
public function testDataTypeForValue(mixed $expectedResult, mixed $value): void
|
||||
{
|
||||
$result = DefaultValueBinder::dataTypeForValue($value);
|
||||
|
||||
@@ -12,6 +12,7 @@ use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class StringValueBinderTest extends TestCase
|
||||
@@ -28,7 +29,7 @@ class StringValueBinderTest extends TestCase
|
||||
Cell::setValueBinder($this->valueBinder);
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataValuesDefault')]
|
||||
#[DataProvider('providerDataValuesDefault')]
|
||||
public function testStringValueBinderDefaultBehaviour(
|
||||
mixed $value,
|
||||
mixed $expectedValue,
|
||||
@@ -96,7 +97,7 @@ class StringValueBinderTest extends TestCase
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataValuesSuppressNullConversion')]
|
||||
#[DataProvider('providerDataValuesSuppressNullConversion')]
|
||||
public function testStringValueBinderSuppressNullConversion(
|
||||
mixed $value,
|
||||
mixed $expectedValue,
|
||||
@@ -123,7 +124,7 @@ class StringValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataValuesSuppressBooleanConversion')]
|
||||
#[DataProvider('providerDataValuesSuppressBooleanConversion')]
|
||||
public function testStringValueBinderSuppressBooleanConversion(
|
||||
mixed $value,
|
||||
mixed $expectedValue,
|
||||
@@ -151,7 +152,7 @@ class StringValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataValuesSuppressNumericConversion')]
|
||||
#[DataProvider('providerDataValuesSuppressNumericConversion')]
|
||||
public function testStringValueBinderSuppressNumericConversion(
|
||||
mixed $value,
|
||||
mixed $expectedValue,
|
||||
@@ -183,10 +184,13 @@ class StringValueBinderTest extends TestCase
|
||||
[true, '1', DataType::TYPE_STRING],
|
||||
[false, '', DataType::TYPE_STRING],
|
||||
[null, '', DataType::TYPE_STRING],
|
||||
'Issue 4766 very large positive exponent scientific notation ignored' => ['4E433', '4E433', DataType::TYPE_STRING],
|
||||
'Issue 4766 very large negative exponent scientific notation ignored' => ['4E-433', '4E-433', DataType::TYPE_STRING],
|
||||
'Issue 4766 small exponent scientific ignored' => ['4E4', '4E4', DataType::TYPE_STRING],
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataValuesSuppressFormulaConversion')]
|
||||
#[DataProvider('providerDataValuesSuppressFormulaConversion')]
|
||||
public function testStringValueBinderSuppressFormulaConversion(
|
||||
mixed $value,
|
||||
mixed $expectedValue,
|
||||
@@ -217,7 +221,7 @@ class StringValueBinderTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('providerDataValuesSuppressAllConversion')]
|
||||
#[DataProvider('providerDataValuesSuppressAllConversion')]
|
||||
public function testStringValueBinderSuppressAllConversion(
|
||||
mixed $value,
|
||||
mixed $expectedValue,
|
||||
|
||||
@@ -86,4 +86,7 @@ return [
|
||||
'Issue 1310 Multiple = at start' => ['s', '======'],
|
||||
'Issue 1310 Variant 1' => ['s', '= ====='],
|
||||
'Issue 1310 Variant 2' => ['s', '=2*3='],
|
||||
'Issue 4766 very large positive exponent treated as string' => ['s', '4E433'],
|
||||
'Issue 4766 very large negative exponent numeric' => ['n', '4E-433'],
|
||||
'Issue 4766 small exponent no decimal point numeric' => ['n', '4E4'],
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user