mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-18 14:06:34 +00:00
b8191244d5
PR #3513, developed by @SaidkhojaIftikhor, has been stuck for some time awaiting tests. This is the first of three PRs to replace that one. This PR also allows the use of slash as a thousands separator or decimal separator or currency symbol. These are, of course, very unusual situations; the main reason to support them is so that PhpSpreadsheet code will not crash when users set those options. New Calculation/Engine and AdvancedValueBinder tests confirm these. While making these changes, a few errors were found in AdvancedValueBinder and Calculation/Engine/FormattedNumber, e.g. currencies weren't parsed correctly when period was used as the group separator and comma as the decimal separator. Tests have been added for those situations.
252 lines
7.4 KiB
PHP
252 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace PhpOffice\PhpSpreadsheetTests\Cell;
|
|
|
|
use PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder;
|
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
|
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
|
|
use PhpOffice\PhpSpreadsheet\Settings;
|
|
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class AdvancedValueBinderTest extends TestCase
|
|
{
|
|
const AVB_PRECISION = 1.0E-8;
|
|
|
|
private string $originalLocale;
|
|
|
|
private string $originalCurrencyCode;
|
|
|
|
private string $originalDecimalSeparator;
|
|
|
|
private string $originalThousandsSeparator;
|
|
|
|
private IValueBinder $valueBinder;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->originalLocale = Settings::getLocale();
|
|
$this->originalCurrencyCode = StringHelper::getCurrencyCode();
|
|
$this->originalDecimalSeparator = StringHelper::getDecimalSeparator();
|
|
$this->originalThousandsSeparator = StringHelper::getThousandsSeparator();
|
|
|
|
$this->valueBinder = Cell::getValueBinder();
|
|
Cell::setValueBinder(new AdvancedValueBinder());
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
StringHelper::setCurrencyCode($this->originalCurrencyCode);
|
|
StringHelper::setDecimalSeparator($this->originalDecimalSeparator);
|
|
StringHelper::setThousandsSeparator($this->originalThousandsSeparator);
|
|
Settings::setLocale($this->originalLocale);
|
|
Cell::setValueBinder($this->valueBinder);
|
|
}
|
|
|
|
public function testNullValue(): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue(null);
|
|
self::assertNull($sheet->getCell('A1')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public function testBoolean(): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue(true);
|
|
self::assertTrue($sheet->getCell('A1')->getValue());
|
|
|
|
$sheet->getCell('A2')->setValue(false);
|
|
self::assertFalse($sheet->getCell('A2')->getValue());
|
|
|
|
$sheet->getCell('A3')->setValue('true');
|
|
self::assertTrue($sheet->getCell('A3')->getValue());
|
|
|
|
$sheet->getCell('A4')->setValue('false');
|
|
self::assertFalse($sheet->getCell('A4')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public function testBooleanLocale(): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
Settings::setLocale('nl_NL');
|
|
|
|
$sheet->getCell('A1')->setValue('Waar');
|
|
self::assertTrue($sheet->getCell('A1')->getValue());
|
|
|
|
$sheet->getCell('A2')->setValue('OnWaar');
|
|
self::assertFalse($sheet->getCell('A2')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
/**
|
|
* @dataProvider currencyProvider
|
|
*
|
|
* @param mixed $value
|
|
* @param mixed $valueBinded
|
|
* @param mixed $thousandsSeparator
|
|
* @param mixed $decimalSeparator
|
|
* @param mixed $currencyCode
|
|
*/
|
|
public function testCurrency($value, $valueBinded, $thousandsSeparator, $decimalSeparator, $currencyCode): void
|
|
{
|
|
StringHelper::setCurrencyCode($currencyCode);
|
|
StringHelper::setDecimalSeparator($decimalSeparator);
|
|
StringHelper::setThousandsSeparator($thousandsSeparator);
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue($value);
|
|
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public static function currencyProvider(): array
|
|
{
|
|
return [
|
|
['$10.11', 10.11, ',', '.', '$'],
|
|
['$1,010.12', 1010.12, ',', '.', '$'],
|
|
['$20,20', 20.2, '.', ',', '$'],
|
|
['$2.020,20', 2020.2, '.', ',', '$'],
|
|
['€2.020,20', 2020.2, '.', ',', '€'],
|
|
['€ 2.020,20', 2020.2, '.', ',', '€'],
|
|
['€2,020.22', 2020.22, ',', '.', '€'],
|
|
['$10.11', 10.11, ',', '.', '€'],
|
|
['€2,020.20', 2020.2, ',', '.', '$'],
|
|
'slash as group separator' => ['€2/020.20', 2020.2, '/', '.', '$'],
|
|
'slash as decimal separator' => ['€2,020/20', 2020.2, ',', '/', '$'],
|
|
['-2,020.20€', -2020.2, ',', '.', '$'],
|
|
['- 2,020.20 € ', -2020.2, ',', '.', '$'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider fractionProvider
|
|
*
|
|
* @param mixed $value
|
|
* @param mixed $valueBinded
|
|
*/
|
|
public function testFractions($value, $valueBinded): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue($value);
|
|
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public static function fractionProvider(): array
|
|
{
|
|
return [
|
|
['1/5', 0.2],
|
|
['-1/5', -0.2],
|
|
['- 1/5', -0.2],
|
|
['12/5', 2.4],
|
|
['2/100', 0.02],
|
|
['15/12', 1.25],
|
|
['20/100', 0.2],
|
|
['1 3/5', 1.6],
|
|
['-1 3/5', -1.6],
|
|
['1 4/20', 1.2],
|
|
['1 16/20', 1.8],
|
|
['12 20/100', 12.2],
|
|
['-1 4/20', -1.2],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider percentageProvider
|
|
*
|
|
* @param mixed $value
|
|
* @param mixed $valueBinded
|
|
*/
|
|
public function testPercentages($value, $valueBinded): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue($value);
|
|
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public static function percentageProvider(): array
|
|
{
|
|
return [
|
|
['10%', 0.1],
|
|
['-12%', -0.12],
|
|
['120%', 1.2],
|
|
['12.5%', 0.125],
|
|
['-12.5%', -0.125],
|
|
['12,345%', 123.45],
|
|
['12,345.67%', 123.4567],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider timeProvider
|
|
*
|
|
* @param mixed $value
|
|
* @param mixed $valueBinded
|
|
*/
|
|
public function testTimes($value, $valueBinded): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue($value);
|
|
self::assertEqualsWithDelta($valueBinded, $sheet->getCell('A1')->getValue(), self::AVB_PRECISION);
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public static function timeProvider(): array
|
|
{
|
|
return [
|
|
['1:20', 0.05555555556],
|
|
['09:17', 0.386805555556],
|
|
['15:00', 0.625],
|
|
['17:12:35', 0.71707175926],
|
|
['23:58:20', 0.99884259259],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider stringProvider
|
|
*/
|
|
public function testStringWrapping(string $value): void
|
|
{
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$sheet->getCell('A1')->setValue($value);
|
|
self::assertEquals($value, $sheet->getCell('A1')->getValue());
|
|
|
|
$spreadsheet->disconnectWorksheets();
|
|
}
|
|
|
|
public static function stringProvider(): array
|
|
{
|
|
return [
|
|
['Hello World', false],
|
|
["Hello\nWorld", true],
|
|
];
|
|
}
|
|
}
|