Extend to Formulas, and Numbers Stored As String

All still require opt-in.
This commit is contained in:
oleibman
2024-12-01 09:20:38 -08:00
parent a68e44eee6
commit 3d6f71f6ad
3 changed files with 59 additions and 21 deletions
+1 -1
View File
@@ -301,7 +301,7 @@ class Html extends BaseReader
/** @var array<int, array<int, string>> */
private static array $falseTrueArray = [];
private function convertBoolean(?string $cellContent): bool|string
private static function convertBoolean(?string $cellContent): bool|string
{
if ($cellContent === '1') {
return true;
+23 -12
View File
@@ -37,9 +37,6 @@ class Html extends BaseWriter
private const DEFAULT_CELL_WIDTH_PIXELS = 56;
private const TRUE_SUBSTITUTE = "\u{fffe}";
private const FALSE_SUBSTITUTE = "\u{feff}";
/**
* Migration aid to tell if html tags will be treated as plaintext in comments.
* if (
@@ -1362,14 +1359,14 @@ class Html extends BaseWriter
if ($this->preCalculateFormulas) {
$origData = $cell->getCalculatedValue();
if ($this->betterBoolean && is_bool($origData)) {
$origData2 = $origData ? self::TRUE_SUBSTITUTE : self::FALSE_SUBSTITUTE;
$origData2 = $origData ? $this->getTrue : $this->getFalse;
} else {
$origData2 = $cell->getCalculatedValueString();
}
} else {
$origData = $cell->getValue();
if ($this->betterBoolean && is_bool($origData)) {
$origData2 = $origData ? self::TRUE_SUBSTITUTE : self::FALSE_SUBSTITUTE;
$origData2 = $origData ? $this->getTrue : $this->getFalse;
} else {
$origData2 = $cell->getValueString();
}
@@ -1414,8 +1411,19 @@ class Html extends BaseWriter
// Extend CSS class?
if (!$this->useInlineCss && is_string($cssClass)) {
$dataType = $cell->getDataType();
if ($this->betterBoolean && $this->preCalculateFormulas && $dataType === DataType::TYPE_FORMULA) {
$calculatedValue = $cell->getCalculatedValue();
if (is_bool($calculatedValue)) {
$dataType = DataType::TYPE_BOOL;
} elseif (is_numeric($calculatedValue)) {
$dataType = DataType::TYPE_NUMERIC;
} elseif (is_string($calculatedValue)) {
$dataType = DataType::TYPE_STRING;
}
}
$cssClass .= ' style' . $cell->getXfIndex();
$cssClass .= ' ' . $cell->getDataType();
$cssClass .= ' ' . $dataType;
} elseif (is_array($cssClass)) {
$index = $cell->getXfIndex();
$styleIndex = 'td.style' . $index . ', th.style' . $index;
@@ -1474,12 +1482,15 @@ class Html extends BaseWriter
$htmlx .= $this->generateRowIncludeCharts($worksheet, $coordinate);
// Column start
$html .= ' <' . $cellType;
if ($cellData === self::TRUE_SUBSTITUTE) {
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
$cellData = $this->getTrue;
} elseif ($cellData === self::FALSE_SUBSTITUTE) {
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
$cellData = $this->getFalse;
if ($this->betterBoolean) {
$dataType = $worksheet->getCell($coordinate)->getDataType();
if ($dataType === DataType::TYPE_BOOL) {
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
} elseif ($dataType === DataType::TYPE_FORMULA && is_bool($worksheet->getCell($coordinate)->getCalculatedValue())) {
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
} elseif (is_numeric($cellData) && $worksheet->getCell($coordinate)->getDataType() === DataType::TYPE_STRING) {
$html .= ' data-type="' . DataType::TYPE_STRING . '"';
}
}
if (!$this->useInlineCss && !$this->isPdf && is_string($cssClass)) {
$html .= ' class="' . $cssClass . '"';
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Reader\Html as HtmlReader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Html as HtmlWriter;
@@ -49,10 +50,13 @@ class BetterBooleanTest extends Functional\AbstractFunctional
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(10);
$sheet->getCell('A1')->setValue(1);
$sheet->getCell('B1')->setValue('Hello');
$sheet->getCell('C1')->setValue(true);
$sheet->getCell('D1')->setValue('=IF(1>2, TRUE, FALSE)');
$sheet->getCell('E1')->setValueExplicit(1, DataType::TYPE_STRING);
$sheet->getCell('F1')->setValue('="A"&"B"');
$sheet->getCell('G1')->setValue('=1+2');
/** @var callable */
$callableWriter = [$this, 'setBetter'];
@@ -60,10 +64,13 @@ class BetterBooleanTest extends Functional\AbstractFunctional
$spreadsheet->disconnectWorksheets();
$rsheet = $reloaded->getActiveSheet();
self::assertSame(10, $rsheet->getCell('A1')->getValue());
self::assertSame(1, $rsheet->getCell('A1')->getValue());
self::assertSame('Hello', $rsheet->getCell('B1')->getValue());
self::assertTrue($rsheet->getCell('C1')->getValue());
self::assertFalse($rsheet->getCell('D1')->getValue());
self::assertSame('1', $rsheet->getCell('E1')->getValue());
self::assertSame('AB', $rsheet->getCell('F1')->getValue());
self::assertSame(3, $rsheet->getCell('G1')->getValue());
$reloaded->disconnectWorksheets();
}
@@ -71,10 +78,13 @@ class BetterBooleanTest extends Functional\AbstractFunctional
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(10);
$sheet->getCell('A1')->setValue(1);
$sheet->getCell('B1')->setValue('Hello');
$sheet->getCell('C1')->setValue(true);
$sheet->getCell('D1')->setValue('=IF(1>2, TRUE, FALSE)');
$sheet->getCell('E1')->setValueExplicit(1, DataType::TYPE_STRING);
$sheet->getCell('F1')->setValue('="A"&"B"');
$sheet->getCell('G1')->setValue('=1+2');
/** @var callable */
$callableWriter = [$this, 'setNotBetter'];
@@ -82,10 +92,13 @@ class BetterBooleanTest extends Functional\AbstractFunctional
$spreadsheet->disconnectWorksheets();
$rsheet = $reloaded->getActiveSheet();
self::assertSame(10, $rsheet->getCell('A1')->getValue());
self::assertSame(1, $rsheet->getCell('A1')->getValue());
self::assertSame('Hello', $rsheet->getCell('B1')->getValue());
self::assertSame(1, $rsheet->getCell('C1')->getValue());
self::assertNull($rsheet->getCell('D1')->getValue());
self::assertSame(1, $rsheet->getCell('E1')->getValue());
self::assertSame('AB', $rsheet->getCell('F1')->getValue());
self::assertSame(3, $rsheet->getCell('G1')->getValue());
$reloaded->disconnectWorksheets();
}
@@ -93,17 +106,24 @@ class BetterBooleanTest extends Functional\AbstractFunctional
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(10);
$sheet->getCell('A1')->setValue(1);
$sheet->getCell('B1')->setValue('Hello');
$sheet->getCell('C1')->setValue(true);
$sheet->getCell('D1')->setValue('=IF(1>2, TRUE, FALSE)');
$sheet->getCell('E1')->setValueExplicit(1, DataType::TYPE_STRING);
$sheet->getCell('F1')->setValue('="A"&"B"');
$sheet->getCell('G1')->setValue('=1+2');
$calc = Calculation::getInstance();
$calc->setLocale('fr');
$writer = new HtmlWriter($spreadsheet);
$writer->setBetterBoolean(true);
$html = $writer->generateHtmlAll();
self::assertStringContainsString('VRAI', $html);
self::assertStringNotContainsString('TRUE', $html);
self::assertStringContainsString('<td data-type="b" class="column2 style0 b">VRAI</td>', $html);
self::assertStringContainsString('<td data-type="b" class="column3 style0 b">FAUX</td>', $html);
self::assertStringContainsString('<td data-type="s" class="column4 style0 s">1</td>', $html);
self::assertStringContainsString('<td class="column5 style0 s">AB</td>', $html);
self::assertStringContainsString('<td class="column6 style0 n">3</td>', $html);
/** @var callable */
$callableWriter = [$this, 'setBetter'];
@@ -111,30 +131,37 @@ class BetterBooleanTest extends Functional\AbstractFunctional
$spreadsheet->disconnectWorksheets();
$rsheet = $reloaded->getActiveSheet();
self::assertSame(10, $rsheet->getCell('A1')->getValue());
self::assertSame(1, $rsheet->getCell('A1')->getValue());
self::assertSame('Hello', $rsheet->getCell('B1')->getValue());
self::assertTrue($rsheet->getCell('C1')->getValue());
self::assertFalse($rsheet->getCell('D1')->getValue());
self::assertSame('1', $rsheet->getCell('E1')->getValue());
self::assertSame('AB', $rsheet->getCell('F1')->getValue());
self::assertSame(3, $rsheet->getCell('G1')->getValue());
$reloaded->disconnectWorksheets();
}
public function testForeignNoLocale(): void
{
$fragment = '<table><tbody><tr>'
. '<td>10</td>'
. '<td>1</td>'
. '<td>Hello</td>'
. '<td data-type="b">ИСТИНА</td>' // Bulgarian TRUE
. '<td data-type="b">EPÄTOSI</td>' // Finnish FALSE
. '<td data-type="b">whatever</td>'
. '<td data-type="b">tRuE</td>'
. '<td data-type="s">1</td>'
. '</tr></tbody></table>';
$reader = new HtmlReader();
$spreadsheet = $reader->loadFromString($fragment);
$sheet = $spreadsheet->getActiveSheet();
self::assertSame(1, $sheet->getCell('A1')->getValue());
self::assertSame('Hello', $sheet->getCell('B1')->getValue());
self::assertTrue($sheet->getCell('C1')->getValue());
self::assertFalse($sheet->getCell('D1')->getValue());
self::assertSame('whatever', $sheet->getCell('E1')->getValue());
self::assertTrue($sheet->getCell('F1')->getValue());
self::assertSame('1', $sheet->getCell('G1')->getValue());
$spreadsheet->disconnectWorksheets();
}
}