Merge branch 'master' into CalcEngine-Refactor-Branch-Pruning
This commit is contained in:
commit
c4f79af56d
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -9,13 +9,23 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
|
||||
### Added
|
||||
|
||||
- Implementation of the ISREF() information function
|
||||
- Implementation of the ISREF() information function.
|
||||
- Added support for reading "formatted" numeric values from Csv files; although default behaviour of reading these values as strings is preserved.
|
||||
|
||||
(i.e a value of "12,345.67" will be read as numeric `1235.67`, not as a string `"12,345.67"`.
|
||||
|
||||
This functionality is locale-aware, using the server's locale settings to identify the thousands and decimal separators.
|
||||
|
||||
### Changed
|
||||
|
||||
- Gnumeric Reader now loads number formatting for cells.
|
||||
- Gnumeric Reader now correctly identifies selected worksheet.
|
||||
- Some Refactoring of the Ods Reader, moving all formula and address translation from Ods to Excel into a separate class to eliminate code duplication and ensure consistency.
|
||||
- Make Boolean Conversion in Csv Reader locale-aware when using the String Value Binder.
|
||||
|
||||
This is determined b the Calculation Engine locale setting.
|
||||
|
||||
(i.e. `"Vrai"` wil be converted to a boolean `true` if the Locale is set to `fr`.)
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
|
@ -27,7 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
|
||||
### Fixed
|
||||
|
||||
- Fixed behaviour of XLSX font style vertical align settings
|
||||
- Fixed behaviour of XLSX font style vertical align settings.
|
||||
- Resolved formula translations to handle separators (row and column) for array functions as well as for function argument separators; and cleanly handle nesting levels.
|
||||
|
||||
Note that this method is used when translating Excel functions between en and other locale languages, as well as when converting formulae between different spreadsheet formats (e.g. Ods to Excel).
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ $spreadsheet->getActiveSheet()
|
|||
### Creating a new Cell
|
||||
|
||||
If you make a call to `getCell()`, and the cell doesn't already exist, then
|
||||
PhpSpreadsheet will (by default) create the cell for you. If you don't want
|
||||
to create a new cell, then you can pass a second argument of false, and then
|
||||
`getCell()` will return a null if the cell doesn't exist.
|
||||
PhpSpreadsheet will create that cell for you.
|
||||
|
||||
### BEWARE: Cells assigned to variables as a Detached Reference
|
||||
|
||||
|
|
@ -532,7 +530,7 @@ types of entered data using a cell's `setValue()` method (the
|
|||
Optionally, the default behaviour of PhpSpreadsheet can be modified,
|
||||
allowing easier data entry. For example, a
|
||||
`\PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder` class is available.
|
||||
It automatically converts percentages, number in scientific format, and
|
||||
It automatically converts percentages, numbers in scientific format, and
|
||||
dates entered as strings to the correct format, also setting the cell's
|
||||
style information. The following example demonstrates how to set the
|
||||
value binder in PhpSpreadsheet:
|
||||
|
|
@ -577,7 +575,9 @@ $stringValueBinder->setNumericConversion(false)
|
|||
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( $stringValueBinder );
|
||||
```
|
||||
|
||||
**Creating your own value binder is relatively straightforward.** When more specialised
|
||||
### Creating your own value binder
|
||||
|
||||
Creating your own value binder is relatively straightforward. When more specialised
|
||||
value binding is required, you can implement the
|
||||
`\PhpOffice\PhpSpreadsheet\Cell\IValueBinder` interface or extend the existing
|
||||
`\PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder` or
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ $conditional->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERA
|
|||
$conditional->addCondition(80);
|
||||
$conditional->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN);
|
||||
$conditional->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
|
||||
$conditional->getStyle()->getFill()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
|
||||
$conditional->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
|
||||
|
||||
$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('A1:A10')->getConditionalStyles();
|
||||
$conditionalStyles[] = $conditional;
|
||||
|
|
@ -63,7 +63,7 @@ $wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFor
|
|||
$wizard->greaterThan(80);
|
||||
$wizard->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN);
|
||||
$wizard->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
|
||||
$wizard->getStyle()->getFill()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
|
||||
$wizard->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
|
||||
|
||||
$conditional = $wizard->getConditional();
|
||||
```
|
||||
|
|
@ -84,7 +84,7 @@ $conditional2->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPER
|
|||
$conditional2->addCondition(10);
|
||||
$conditional2->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKRED);
|
||||
$conditional2->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
|
||||
$conditional2->getStyle()->getFill()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
|
||||
$conditional2->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
|
||||
|
||||
$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('A1:A10')->getConditionalStyles();
|
||||
$conditionalStyles[] = $conditional2;
|
||||
|
|
@ -98,7 +98,7 @@ $wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFor
|
|||
$wizard->lessThan(10);
|
||||
$wizard->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN);
|
||||
$wizard->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
|
||||
$wizard->getStyle()->getFill()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
|
||||
$wizard->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN);
|
||||
|
||||
$conditional = $wizard->getConditional();
|
||||
```
|
||||
|
|
|
|||
|
|
@ -560,6 +560,44 @@ Xlsx | NO | Xls | NO | Xml | NO |
|
|||
Ods | NO | SYLK | NO | Gnumeric | NO |
|
||||
CSV | YES | HTML | NO
|
||||
|
||||
|
||||
### Reading formatted Numbers from a CSV File
|
||||
|
||||
Unfortunately, numbers in a CSV file may be formatted as strings.
|
||||
If that number is a simple integer or float (with a decimal `.` separator) without any thousands separator, then it will be treated as a number.
|
||||
However, if the value has a thousands separator (e.g. `12,345`), or a decimal separator that isn't a `.` (e.g. `123,45` for a European locale), then it will be loaded as a string with that formatting.
|
||||
If you want the Csv Reader to convert that value to a numeric when it loads the file, the you need to tell it to do so. The `castFormattedNumberToNumeric()` lets you do this.
|
||||
|
||||
(Assuming that our server is configured with German locale settings: otherwise it may be necessary to call `setlocale()` before loading the file.)
|
||||
```php
|
||||
$inputFileType = 'Csv';
|
||||
$inputFileName = './sampleData/example1.de.csv';
|
||||
|
||||
/** It may be necessary to call setlocale() first if this is not your default locale */
|
||||
// setlocale(LC_ALL, 'de_DE.UTF-8', 'deu_deu');
|
||||
|
||||
/** Create a new Reader of the type defined in $inputFileType **/
|
||||
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
|
||||
/** Enable loading numeric values formatted with German , decimal separator and . thousands separator **/
|
||||
$reader->castFormattedNumberToNumeric(true);
|
||||
|
||||
/** Load the file to a Spreadsheet Object **/
|
||||
$spreadsheet = $reader->load($inputFileName);
|
||||
```
|
||||
This will attempt to load those formatted numeric values as numbers, based on the server's locale settings.
|
||||
|
||||
If you want to load those values as numbers, but also to retain the formatting as a number format mask, then you can pass a boolean `true` as a second argument to the `castFormattedNumberToNumeric()` method to tell the Reader to identify the format masking to use for that value. This option does have an arbitrary limit of 6 decimal places.
|
||||
|
||||
If your Csv file includes other formats for numbers (currencies, scientific format, etc); then you should probably also use the Advanced Value Binder to handle these cases.
|
||||
|
||||
Applies to:
|
||||
|
||||
Reader | Y/N |Reader | Y/N |Reader | Y/N |
|
||||
----------|:---:|--------|:---:|--------------|:---:|
|
||||
Xlsx | NO | Xls | NO | Xml | NO |
|
||||
Ods | NO | SYLK | NO | Gnumeric | NO |
|
||||
CSV | YES | HTML | NO
|
||||
|
||||
### A Brief Word about the Advanced Value Binder
|
||||
|
||||
When loading data from a file that contains no formatting information,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Csv\Delimiter;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
|
||||
class Csv extends BaseReader
|
||||
{
|
||||
|
|
@ -91,6 +93,16 @@ class Csv extends BaseReader
|
|||
*/
|
||||
private $testAutodetect = true;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $castFormattedNumberToNumeric = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $preserveNumericFormatting = false;
|
||||
|
||||
/**
|
||||
* Create a new CSV Reader instance.
|
||||
*/
|
||||
|
|
@ -294,6 +306,14 @@ class Csv extends BaseReader
|
|||
return $retVal;
|
||||
}
|
||||
|
||||
public function castFormattedNumberToNumeric(
|
||||
bool $castFormattedNumberToNumeric,
|
||||
bool $preserveNumericFormatting = false
|
||||
): void {
|
||||
$this->castFormattedNumberToNumeric = $castFormattedNumberToNumeric;
|
||||
$this->preserveNumericFormatting = $preserveNumericFormatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
|
||||
*/
|
||||
|
|
@ -330,6 +350,7 @@ class Csv extends BaseReader
|
|||
$columnLetter = 'A';
|
||||
foreach ($rowData as $rowDatum) {
|
||||
$this->convertBoolean($rowDatum, $preserveBooleanString);
|
||||
$numberFormatMask = $this->convertFormattedNumber($rowDatum);
|
||||
if ($rowDatum !== '' && $this->readFilter->readCell($columnLetter, $currentRow)) {
|
||||
if ($this->contiguous) {
|
||||
if ($noOutputYet) {
|
||||
|
|
@ -339,6 +360,10 @@ class Csv extends BaseReader
|
|||
} else {
|
||||
$outRow = $currentRow;
|
||||
}
|
||||
// Set basic styling for the value (Note that this could be overloaded by styling in a value binder)
|
||||
$sheet->getCell($columnLetter . $outRow)->getStyle()
|
||||
->getNumberFormat()
|
||||
->setFormatCode($numberFormatMask);
|
||||
// Set cell value
|
||||
$sheet->getCell($columnLetter . $outRow)->setValue($rowDatum);
|
||||
}
|
||||
|
|
@ -365,9 +390,9 @@ class Csv extends BaseReader
|
|||
private function convertBoolean(&$rowDatum, bool $preserveBooleanString): void
|
||||
{
|
||||
if (is_string($rowDatum) && !$preserveBooleanString) {
|
||||
if (strcasecmp('true', $rowDatum) === 0) {
|
||||
if (strcasecmp(Calculation::getTRUE(), $rowDatum) === 0 || strcasecmp('true', $rowDatum) === 0) {
|
||||
$rowDatum = true;
|
||||
} elseif (strcasecmp('false', $rowDatum) === 0) {
|
||||
} elseif (strcasecmp(Calculation::getFALSE(), $rowDatum) === 0 || strcasecmp('false', $rowDatum) === 0) {
|
||||
$rowDatum = false;
|
||||
}
|
||||
} elseif ($rowDatum === null) {
|
||||
|
|
@ -375,6 +400,39 @@ class Csv extends BaseReader
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert numeric strings to int or float values.
|
||||
*
|
||||
* @param mixed $rowDatum
|
||||
*/
|
||||
private function convertFormattedNumber(&$rowDatum): string
|
||||
{
|
||||
$numberFormatMask = NumberFormat::FORMAT_GENERAL;
|
||||
if ($this->castFormattedNumberToNumeric === true && is_string($rowDatum)) {
|
||||
$numeric = str_replace(
|
||||
[StringHelper::getThousandsSeparator(), StringHelper::getDecimalSeparator()],
|
||||
['', '.'],
|
||||
$rowDatum
|
||||
);
|
||||
|
||||
if (is_numeric($numeric)) {
|
||||
$decimalPos = strpos($rowDatum, StringHelper::getDecimalSeparator());
|
||||
if ($this->preserveNumericFormatting === true) {
|
||||
$numberFormatMask = (strpos($rowDatum, StringHelper::getThousandsSeparator()) !== false)
|
||||
? '#,##0' : '0';
|
||||
if ($decimalPos !== false) {
|
||||
$decimals = strlen($rowDatum) - $decimalPos - 1;
|
||||
$numberFormatMask .= '.' . str_repeat('0', min($decimals, 6));
|
||||
}
|
||||
}
|
||||
|
||||
$rowDatum = ($decimalPos !== false) ? (float) $numeric : (int) $numeric;
|
||||
}
|
||||
}
|
||||
|
||||
return $numberFormatMask;
|
||||
}
|
||||
|
||||
public function getDelimiter(): ?string
|
||||
{
|
||||
return $this->delimiter;
|
||||
|
|
|
|||
|
|
@ -1101,8 +1101,8 @@ class Xls extends BaseReader
|
|||
$height = SharedXls::getDistanceY($this->phpSheet, $startRow, $startOffsetY, $endRow, $endOffsetY);
|
||||
|
||||
// calculate offsetX and offsetY of the shape
|
||||
$offsetX = $startOffsetX * SharedXls::sizeCol($this->phpSheet, $startColumn) / 1024;
|
||||
$offsetY = $startOffsetY * SharedXls::sizeRow($this->phpSheet, $startRow) / 256;
|
||||
$offsetX = (int) ($startOffsetX * SharedXls::sizeCol($this->phpSheet, $startColumn) / 1024);
|
||||
$offsetY = (int) ($startOffsetY * SharedXls::sizeRow($this->phpSheet, $startRow) / 256);
|
||||
|
||||
switch ($obj['otObjType']) {
|
||||
case 0x19:
|
||||
|
|
|
|||
|
|
@ -52,6 +52,18 @@ class ImCscTest extends TestCase
|
|||
|
||||
$formula = "=IMCSC({$complex})";
|
||||
$result = $calculation->_calculateFormulaValue($formula);
|
||||
// Avoid testing for excess precision
|
||||
foreach ($expectedResult as &$array) {
|
||||
foreach ($array as &$string) {
|
||||
$string = preg_replace('/(\\d{8})\\d+/', '$1', $string);
|
||||
}
|
||||
}
|
||||
foreach ($result as &$array) {
|
||||
foreach ($array as &$string) {
|
||||
$string = preg_replace('/(\\d{8})\\d+/', '$1', $string);
|
||||
}
|
||||
}
|
||||
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
|
||||
|
|
@ -31,7 +32,7 @@ class CsvIssue2232Test extends TestCase
|
|||
* @param mixed $b2Value
|
||||
* @param mixed $b3Value
|
||||
*/
|
||||
public function testEncodings(bool $useStringBinder, ?bool $preserveBoolString, $b2Value, $b3Value): void
|
||||
public function testBooleanConversions(bool $useStringBinder, ?bool $preserveBoolString, $b2Value, $b3Value): void
|
||||
{
|
||||
if ($useStringBinder) {
|
||||
$binder = new StringValueBinder();
|
||||
|
|
@ -60,4 +61,41 @@ class CsvIssue2232Test extends TestCase
|
|||
[true, true, 'FaLSe', 'tRUE'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerIssue2232locale
|
||||
*
|
||||
* @param mixed $b4Value
|
||||
* @param mixed $b5Value
|
||||
*/
|
||||
public function testBooleanConversionsLocaleAware(bool $useStringBinder, ?bool $preserveBoolString, $b4Value, $b5Value): void
|
||||
{
|
||||
if ($useStringBinder) {
|
||||
$binder = new StringValueBinder();
|
||||
if (is_bool($preserveBoolString)) {
|
||||
$binder->setBooleanConversion($preserveBoolString);
|
||||
}
|
||||
Cell::setValueBinder($binder);
|
||||
}
|
||||
|
||||
Calculation::getInstance()->setLocale('fr');
|
||||
|
||||
$reader = new Csv();
|
||||
$filename = 'tests/data/Reader/CSV/issue.2232.csv';
|
||||
$spreadsheet = $reader->load($filename);
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
self::assertSame($b4Value, $sheet->getCell('B4')->getValue());
|
||||
self::assertSame($b5Value, $sheet->getCell('B5')->getValue());
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
public function providerIssue2232locale(): array
|
||||
{
|
||||
return [
|
||||
[true, true, 'Faux', 'Vrai'],
|
||||
[true, true, 'Faux', 'Vrai'],
|
||||
[false, false, false, true],
|
||||
[false, false, false, true],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Csv;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CsvNumberFormatLocaleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $localeAdjusted;
|
||||
|
||||
/**
|
||||
* @var false|string
|
||||
*/
|
||||
private $currentLocale;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* @var Csv
|
||||
*/
|
||||
protected $csvReader;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->currentLocale = setlocale(LC_ALL, '0');
|
||||
|
||||
if (!setlocale(LC_ALL, 'de_DE.UTF-8', 'deu_deu')) {
|
||||
$this->localeAdjusted = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->localeAdjusted = true;
|
||||
|
||||
$this->filename = 'tests/data/Reader/CSV/NumberFormatTest.de.csv';
|
||||
$this->csvReader = new Csv();
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
if ($this->localeAdjusted && is_string($this->currentLocale)) {
|
||||
setlocale(LC_ALL, $this->currentLocale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerNumberFormatNoConversionTest
|
||||
*
|
||||
* @param mixed $expectedValue
|
||||
*/
|
||||
public function testNumberFormatNoConversion($expectedValue, string $expectedFormat, string $cellAddress): void
|
||||
{
|
||||
if (!$this->localeAdjusted) {
|
||||
self::markTestSkipped('Unable to set locale for testing.');
|
||||
}
|
||||
|
||||
$spreadsheet = $this->csvReader->load($this->filename);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$cell = $worksheet->getCell($cellAddress);
|
||||
|
||||
self::assertSame($expectedValue, $cell->getValue(), 'Expected value check');
|
||||
self::assertSame($expectedFormat, $cell->getFormattedValue(), 'Format mask check');
|
||||
}
|
||||
|
||||
public function providerNumberFormatNoConversionTest(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
-123,
|
||||
'-123',
|
||||
'A1',
|
||||
],
|
||||
[
|
||||
'12.345,67',
|
||||
'12.345,67',
|
||||
'C1',
|
||||
],
|
||||
[
|
||||
'-1.234,567',
|
||||
'-1.234,567',
|
||||
'A3',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerNumberValueConversionTest
|
||||
*
|
||||
* @param mixed $expectedValue
|
||||
*/
|
||||
public function testNumberValueConversion($expectedValue, string $cellAddress): void
|
||||
{
|
||||
if (!$this->localeAdjusted) {
|
||||
self::markTestSkipped('Unable to set locale for testing.');
|
||||
}
|
||||
|
||||
$this->csvReader->castFormattedNumberToNumeric(true);
|
||||
$spreadsheet = $this->csvReader->load($this->filename);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$cell = $worksheet->getCell($cellAddress);
|
||||
|
||||
self::assertSame(DataType::TYPE_NUMERIC, $cell->getDataType(), 'Datatype check');
|
||||
self::assertSame($expectedValue, $cell->getValue(), 'Expected value check');
|
||||
}
|
||||
|
||||
public function providerNumberValueConversionTest(): array
|
||||
{
|
||||
return [
|
||||
'A1' => [
|
||||
-123,
|
||||
'A1',
|
||||
],
|
||||
'B1' => [
|
||||
1234,
|
||||
'B1',
|
||||
],
|
||||
'C1' => [
|
||||
12345.67,
|
||||
'C1',
|
||||
],
|
||||
'A2' => [
|
||||
123.4567,
|
||||
'A2',
|
||||
],
|
||||
'B2' => [
|
||||
123.456789012,
|
||||
'B2',
|
||||
],
|
||||
'A3' => [
|
||||
-1234.567,
|
||||
'A3',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Csv;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CsvNumberFormatTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* @var Csv
|
||||
*/
|
||||
protected $csvReader;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->filename = 'tests/data/Reader/CSV/NumberFormatTest.csv';
|
||||
$this->csvReader = new Csv();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerNumberFormatNoConversionTest
|
||||
*
|
||||
* @param mixed $expectedValue
|
||||
*/
|
||||
public function testNumberFormatNoConversion($expectedValue, string $expectedFormat, string $cellAddress): void
|
||||
{
|
||||
$spreadsheet = $this->csvReader->load($this->filename);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$cell = $worksheet->getCell($cellAddress);
|
||||
|
||||
self::assertSame($expectedValue, $cell->getValue(), 'Expected value check');
|
||||
self::assertSame($expectedFormat, $cell->getFormattedValue(), 'Format mask check');
|
||||
}
|
||||
|
||||
public function providerNumberFormatNoConversionTest(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
-123,
|
||||
'-123',
|
||||
'A1',
|
||||
],
|
||||
[
|
||||
'12,345.67',
|
||||
'12,345.67',
|
||||
'C1',
|
||||
],
|
||||
[
|
||||
'-1,234.567',
|
||||
'-1,234.567',
|
||||
'A3',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerNumberValueConversionTest
|
||||
*
|
||||
* @param mixed $expectedValue
|
||||
*/
|
||||
public function testNumberValueConversion($expectedValue, string $cellAddress): void
|
||||
{
|
||||
$this->csvReader->castFormattedNumberToNumeric(true);
|
||||
$spreadsheet = $this->csvReader->load($this->filename);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$cell = $worksheet->getCell($cellAddress);
|
||||
|
||||
self::assertSame(DataType::TYPE_NUMERIC, $cell->getDataType(), 'Datatype check');
|
||||
self::assertSame($expectedValue, $cell->getValue(), 'Expected value check');
|
||||
}
|
||||
|
||||
public function providerNumberValueConversionTest(): array
|
||||
{
|
||||
return [
|
||||
'A1' => [
|
||||
-123,
|
||||
'A1',
|
||||
],
|
||||
'B1' => [
|
||||
1234,
|
||||
'B1',
|
||||
],
|
||||
'C1' => [
|
||||
12345.67,
|
||||
'C1',
|
||||
],
|
||||
'A2' => [
|
||||
123.4567,
|
||||
'A2',
|
||||
],
|
||||
'B2' => [
|
||||
123.456789012,
|
||||
'B2',
|
||||
],
|
||||
'A3' => [
|
||||
-1234.567,
|
||||
'A3',
|
||||
],
|
||||
'B3' => [
|
||||
1234.567,
|
||||
'B3',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerNumberFormatConversionTest
|
||||
*
|
||||
* @param mixed $expectedValue
|
||||
*/
|
||||
public function testNumberFormatConversion($expectedValue, string $expectedFormat, string $cellAddress): void
|
||||
{
|
||||
$this->csvReader->castFormattedNumberToNumeric(true, true);
|
||||
$spreadsheet = $this->csvReader->load($this->filename);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$cell = $worksheet->getCell($cellAddress);
|
||||
|
||||
self::assertSame(DataType::TYPE_NUMERIC, $cell->getDataType(), 'Datatype check');
|
||||
self::assertSame($expectedValue, $cell->getValue(), 'Expected value check');
|
||||
self::assertSame($expectedFormat, $cell->getFormattedValue(), 'Format mask check');
|
||||
}
|
||||
|
||||
public function providerNumberFormatConversionTest(): array
|
||||
{
|
||||
return [
|
||||
'A1' => [
|
||||
-123,
|
||||
'-123',
|
||||
'A1',
|
||||
],
|
||||
'B1' => [
|
||||
1234,
|
||||
'1,234',
|
||||
'B1',
|
||||
],
|
||||
'C1' => [
|
||||
12345.67,
|
||||
'12,345.67',
|
||||
'C1',
|
||||
],
|
||||
'A2' => [
|
||||
123.4567,
|
||||
'123.4567',
|
||||
'A2',
|
||||
],
|
||||
'B2' => [
|
||||
123.456789012,
|
||||
'123.456789',
|
||||
'B2',
|
||||
],
|
||||
'A3' => [
|
||||
-1234.567,
|
||||
'-1,234.567',
|
||||
'A3',
|
||||
],
|
||||
'B3' => [
|
||||
1234.567,
|
||||
'1234.567',
|
||||
'B3',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
"-123","1,234","12,345.67"
|
||||
"123.4567","123.456789012"
|
||||
"-1,234.567",1234.567
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
|
@ -0,0 +1,3 @@
|
|||
"-123","1.234","12.345,67"
|
||||
"123,4567","123,456789012"
|
||||
"-1.234,567"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
|
@ -1,3 +1,5 @@
|
|||
1,2,3
|
||||
a,FaLSe,b
|
||||
cc,tRUE,cc
|
||||
dd,Faux,ee
|
||||
ff,Vrai,gg
|
||||
|
|
|
|||
|
Loading…
Reference in New Issue