Files
PhpSpreadsheet/tests/PhpSpreadsheetTests/Writer/Html/HtmlNumberFormatTest.php
T
oleibman 9bef9c90ce Tests Involving Decimal and Currency Separators
This was suggested by the investigation of issue #3811. No fix is necessary for the issue. However, two possible code solutions (Php setlocale, which comes with certain design flaws, and StringHelper set(Decimal/Thousands)Separator were suggested, and neither is adequately tested. This PR adds such tests.

Unusually, getting StringHelper Decimal Separator, Thousands Separator, and Currency Code can result in a change to those properties. So, the existing design in several tests where those properties are captured in Setup and restored in Teardown do not work quite as designed. Instead, the ability to set those properties to their default value (null) is added, and the tests re-done to restore the default in Teardown.

The two methods yield the same results when parsing input. However, they diverge when examining output fields through `getFormattedValue`. Such output is currently correct (usually) when using setlocale, but not when using StringHelper. The former works through the 'trick' of using `sprintf(%f)`, which generates a locale-aware string. However, using non-locale-aware `sprintf(%F)` followed by `str_replace` will produce the correct result for both setlocale and StringHelper. One place in the code uses a cast to string, which is incorrect for both methods. Following that up with the same str_replace makes it correct for both. These changes permit, but do not require, the user to avoid setlocale altogether.

It remains an open question whether Settings/Calculation::setLocale should set DecimalSeparator, CurrencySeparator, and CurrencyCode. That makes logical sense, but it would be a breaking change, and having to explicitly set those values when using setLocale does not seem especially burdensome. For now, such a change will not be made.
2023-12-07 22:49:43 -08:00

202 lines
7.4 KiB
PHP

<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
use DOMDocument;
use PhpOffice\PhpSpreadsheet\Settings;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Html;
use PhpOffice\PhpSpreadsheetTests\Functional;
class HtmlNumberFormatTest extends Functional\AbstractFunctional
{
protected function setUp(): void
{
StringHelper::setCurrencyCode('$');
StringHelper::setDecimalSeparator('.');
StringHelper::setThousandsSeparator(',');
}
protected function tearDown(): void
{
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
}
public function testColorNumberFormat(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', -50);
$sheet->setCellValue('A2', 3000);
$sheet->setCellValue('A3', 0);
$sheet->setCellValue('A4', '<br>');
$fmt = '[Blue]$#,##0;[Red]$#,##0;$#,##0';
$sheet->getStyle('A1:A4')->getNumberFormat()->setFormatCode($fmt);
$writer = new Html($spreadsheet);
$html = $writer->generateHTMLAll();
$dom = new DOMDocument();
$dom->loadHTML($html);
$body = $dom->getElementsByTagName('body')[0];
$divs = $body->getElementsByTagName('div');
$tabl = $divs[0]->getElementsByTagName('table');
$tbod = $tabl[0]->getElementsByTagName('tbody');
$rows = $tbod[0]->getElementsByTagName('tr');
self::assertCount(4, $rows);
$tds = $rows[0]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(1, $spans);
$style = $spans[0]->getAttribute('style');
self::assertEquals(1, preg_match('/color:red/', $style));
self::assertEquals('$50', $spans[0]->textContent);
$tds = $rows[1]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(1, $spans);
$style = $spans[0]->getAttribute('style');
self::assertEquals(1, preg_match('/color:blue/', $style));
self::assertEquals('$3,000', $spans[0]->textContent);
$tds = $rows[2]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(0, $spans);
self::assertEquals('$0', $tds[0]->textContent);
$tds = $rows[3]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(0, $spans);
self::assertEquals('<br>', $tds[0]->textContent);
$this->writeAndReload($spreadsheet, 'Html');
}
public function testColorNumberFormatComplex(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', -50);
$sheet->setCellValue('A2', 3000.75);
$sheet->setCellValue('A3', 0);
$sheet->setCellValue('A4', 3000.25);
$fmt = '[Blue][>=3000.5]$#,##0.00;[Red][<0]$#,##0.00;$#,##0.00';
$sheet->getStyle('A1:A4')->getNumberFormat()->setFormatCode($fmt);
$writer = new Html($spreadsheet);
$html = $writer->generateHTMLAll();
$dom = new DOMDocument();
$dom->loadHTML($html);
$body = $dom->getElementsByTagName('body')[0];
$divs = $body->getElementsByTagName('div');
$tabl = $divs[0]->getElementsByTagName('table');
$tbod = $tabl[0]->getElementsByTagName('tbody');
$rows = $tbod[0]->getElementsByTagName('tr');
self::assertCount(4, $rows);
$tds = $rows[0]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(1, $spans);
$style = $spans[0]->getAttribute('style');
self::assertEquals(1, preg_match('/color:red/', $style));
self::assertEquals('$50.00', $spans[0]->textContent);
$tds = $rows[1]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(1, $spans);
$style = $spans[0]->getAttribute('style');
self::assertEquals(1, preg_match('/color:blue/', $style));
self::assertEquals('$3,000.75', $spans[0]->textContent);
$tds = $rows[2]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(0, $spans);
self::assertEquals('$0.00', $tds[0]->textContent);
$tds = $rows[3]->getElementsByTagName('td');
self::assertCount(1, $tds);
$spans = $tds[0]->getElementsByTagName('span');
self::assertCount(0, $spans);
self::assertEquals('$3,000.25', $tds[0]->textContent);
$this->writeAndReload($spreadsheet, 'Html');
}
/**
* @dataProvider providerNumberFormat
*/
public function testFormatValueWithMask(mixed $expectedResult, mixed $val, mixed $fmt): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($val)->getStyle()->getNumberFormat()->setFormatCode($fmt);
$writer = new Html($spreadsheet);
$html = $writer->generateHTMLAll();
$dom = new DOMDocument();
$dom->loadHTML($html);
$body = $dom->getElementsByTagName('body')[0];
$divs = $body->getElementsByTagName('div');
$tabl = $divs[0]->getElementsByTagName('table');
$tbod = $tabl[0]->getElementsByTagName('tbody');
$rows = $tbod[0]->getElementsByTagName('tr');
$tds = $rows[0]->getElementsByTagName('td');
$nbsp = html_entity_decode('&nbsp;', Settings::htmlEntityFlags());
self::assertEquals($expectedResult, str_replace($nbsp, ' ', $tds[0]->textContent));
$this->writeAndReload($spreadsheet, 'Html');
}
public static function providerNumberFormat(): array
{
return require __DIR__ . '/../../../data/Style/NumberFormat.php';
}
/**
* @dataProvider providerNumberFormatDates
*/
public function testFormatValueWithMaskDate(mixed $expectedResult, mixed $val, mixed $fmt): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($val)->getStyle()->getNumberFormat()->setFormatCode($fmt);
$writer = new Html($spreadsheet);
$html = $writer->generateHTMLAll();
$dom = new DOMDocument();
$dom->loadHTML($html);
$body = $dom->getElementsByTagName('body')[0];
$divs = $body->getElementsByTagName('div');
$tabl = $divs[0]->getElementsByTagName('table');
$tbod = $tabl[0]->getElementsByTagName('tbody');
$rows = $tbod[0]->getElementsByTagName('tr');
$tds = $rows[0]->getElementsByTagName('td');
$nbsp = html_entity_decode('&nbsp;', Settings::htmlEntityFlags());
self::assertEquals($expectedResult, str_replace($nbsp, ' ', $tds[0]->textContent));
$this->writeAndReload($spreadsheet, 'Html');
}
public static function providerNumberFormatDates(): array
{
return require __DIR__ . '/../../../data/Style/NumberFormatDates.php';
}
}