Skip to content

Commit 3d6f71f

Browse files
committed
Extend to Formulas, and Numbers Stored As String
All still require opt-in.
1 parent a68e44e commit 3d6f71f

File tree

3 files changed

+59
-21
lines changed

3 files changed

+59
-21
lines changed

src/PhpSpreadsheet/Reader/Html.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ protected function flushCell(Worksheet $sheet, string $column, int|string $row,
301301
/** @var array<int, array<int, string>> */
302302
private static array $falseTrueArray = [];
303303

304-
private function convertBoolean(?string $cellContent): bool|string
304+
private static function convertBoolean(?string $cellContent): bool|string
305305
{
306306
if ($cellContent === '1') {
307307
return true;

src/PhpSpreadsheet/Writer/Html.php

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ class Html extends BaseWriter
3737

3838
private const DEFAULT_CELL_WIDTH_PIXELS = 56;
3939

40-
private const TRUE_SUBSTITUTE = "\u{fffe}";
41-
private const FALSE_SUBSTITUTE = "\u{feff}";
42-
4340
/**
4441
* Migration aid to tell if html tags will be treated as plaintext in comments.
4542
* if (
@@ -1362,14 +1359,14 @@ private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, stri
13621359
if ($this->preCalculateFormulas) {
13631360
$origData = $cell->getCalculatedValue();
13641361
if ($this->betterBoolean && is_bool($origData)) {
1365-
$origData2 = $origData ? self::TRUE_SUBSTITUTE : self::FALSE_SUBSTITUTE;
1362+
$origData2 = $origData ? $this->getTrue : $this->getFalse;
13661363
} else {
13671364
$origData2 = $cell->getCalculatedValueString();
13681365
}
13691366
} else {
13701367
$origData = $cell->getValue();
13711368
if ($this->betterBoolean && is_bool($origData)) {
1372-
$origData2 = $origData ? self::TRUE_SUBSTITUTE : self::FALSE_SUBSTITUTE;
1369+
$origData2 = $origData ? $this->getTrue : $this->getFalse;
13731370
} else {
13741371
$origData2 = $cell->getValueString();
13751372
}
@@ -1414,8 +1411,19 @@ private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cel
14141411

14151412
// Extend CSS class?
14161413
if (!$this->useInlineCss && is_string($cssClass)) {
1414+
$dataType = $cell->getDataType();
1415+
if ($this->betterBoolean && $this->preCalculateFormulas && $dataType === DataType::TYPE_FORMULA) {
1416+
$calculatedValue = $cell->getCalculatedValue();
1417+
if (is_bool($calculatedValue)) {
1418+
$dataType = DataType::TYPE_BOOL;
1419+
} elseif (is_numeric($calculatedValue)) {
1420+
$dataType = DataType::TYPE_NUMERIC;
1421+
} elseif (is_string($calculatedValue)) {
1422+
$dataType = DataType::TYPE_STRING;
1423+
}
1424+
}
14171425
$cssClass .= ' style' . $cell->getXfIndex();
1418-
$cssClass .= ' ' . $cell->getDataType();
1426+
$cssClass .= ' ' . $dataType;
14191427
} elseif (is_array($cssClass)) {
14201428
$index = $cell->getXfIndex();
14211429
$styleIndex = 'td.style' . $index . ', th.style' . $index;
@@ -1474,12 +1482,15 @@ private function generateRowWriteCell(
14741482
$htmlx .= $this->generateRowIncludeCharts($worksheet, $coordinate);
14751483
// Column start
14761484
$html .= ' <' . $cellType;
1477-
if ($cellData === self::TRUE_SUBSTITUTE) {
1478-
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
1479-
$cellData = $this->getTrue;
1480-
} elseif ($cellData === self::FALSE_SUBSTITUTE) {
1481-
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
1482-
$cellData = $this->getFalse;
1485+
if ($this->betterBoolean) {
1486+
$dataType = $worksheet->getCell($coordinate)->getDataType();
1487+
if ($dataType === DataType::TYPE_BOOL) {
1488+
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
1489+
} elseif ($dataType === DataType::TYPE_FORMULA && is_bool($worksheet->getCell($coordinate)->getCalculatedValue())) {
1490+
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
1491+
} elseif (is_numeric($cellData) && $worksheet->getCell($coordinate)->getDataType() === DataType::TYPE_STRING) {
1492+
$html .= ' data-type="' . DataType::TYPE_STRING . '"';
1493+
}
14831494
}
14841495
if (!$this->useInlineCss && !$this->isPdf && is_string($cssClass)) {
14851496
$html .= ' class="' . $cssClass . '"';

tests/PhpSpreadsheetTests/Writer/Html/BetterBooleanTest.php

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpOffice\PhpSpreadsheetTests\Writer\Html;
66

77
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
8+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
89
use PhpOffice\PhpSpreadsheet\Reader\Html as HtmlReader;
910
use PhpOffice\PhpSpreadsheet\Spreadsheet;
1011
use PhpOffice\PhpSpreadsheet\Writer\Html as HtmlWriter;
@@ -49,92 +50,118 @@ public function testBetterBoolean(): void
4950
{
5051
$spreadsheet = new Spreadsheet();
5152
$sheet = $spreadsheet->getActiveSheet();
52-
$sheet->getCell('A1')->setValue(10);
53+
$sheet->getCell('A1')->setValue(1);
5354
$sheet->getCell('B1')->setValue('Hello');
5455
$sheet->getCell('C1')->setValue(true);
5556
$sheet->getCell('D1')->setValue('=IF(1>2, TRUE, FALSE)');
57+
$sheet->getCell('E1')->setValueExplicit(1, DataType::TYPE_STRING);
58+
$sheet->getCell('F1')->setValue('="A"&"B"');
59+
$sheet->getCell('G1')->setValue('=1+2');
5660

5761
/** @var callable */
5862
$callableWriter = [$this, 'setBetter'];
5963
$reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
6064
$spreadsheet->disconnectWorksheets();
6165

6266
$rsheet = $reloaded->getActiveSheet();
63-
self::assertSame(10, $rsheet->getCell('A1')->getValue());
67+
self::assertSame(1, $rsheet->getCell('A1')->getValue());
6468
self::assertSame('Hello', $rsheet->getCell('B1')->getValue());
6569
self::assertTrue($rsheet->getCell('C1')->getValue());
6670
self::assertFalse($rsheet->getCell('D1')->getValue());
71+
self::assertSame('1', $rsheet->getCell('E1')->getValue());
72+
self::assertSame('AB', $rsheet->getCell('F1')->getValue());
73+
self::assertSame(3, $rsheet->getCell('G1')->getValue());
6774
$reloaded->disconnectWorksheets();
6875
}
6976

7077
public function testNotBetterBoolean(): void
7178
{
7279
$spreadsheet = new Spreadsheet();
7380
$sheet = $spreadsheet->getActiveSheet();
74-
$sheet->getCell('A1')->setValue(10);
81+
$sheet->getCell('A1')->setValue(1);
7582
$sheet->getCell('B1')->setValue('Hello');
7683
$sheet->getCell('C1')->setValue(true);
7784
$sheet->getCell('D1')->setValue('=IF(1>2, TRUE, FALSE)');
85+
$sheet->getCell('E1')->setValueExplicit(1, DataType::TYPE_STRING);
86+
$sheet->getCell('F1')->setValue('="A"&"B"');
87+
$sheet->getCell('G1')->setValue('=1+2');
7888

7989
/** @var callable */
8090
$callableWriter = [$this, 'setNotBetter'];
8191
$reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
8292
$spreadsheet->disconnectWorksheets();
8393

8494
$rsheet = $reloaded->getActiveSheet();
85-
self::assertSame(10, $rsheet->getCell('A1')->getValue());
95+
self::assertSame(1, $rsheet->getCell('A1')->getValue());
8696
self::assertSame('Hello', $rsheet->getCell('B1')->getValue());
8797
self::assertSame(1, $rsheet->getCell('C1')->getValue());
8898
self::assertNull($rsheet->getCell('D1')->getValue());
99+
self::assertSame(1, $rsheet->getCell('E1')->getValue());
100+
self::assertSame('AB', $rsheet->getCell('F1')->getValue());
101+
self::assertSame(3, $rsheet->getCell('G1')->getValue());
89102
$reloaded->disconnectWorksheets();
90103
}
91104

92105
public function testLocale(): void
93106
{
94107
$spreadsheet = new Spreadsheet();
95108
$sheet = $spreadsheet->getActiveSheet();
96-
$sheet->getCell('A1')->setValue(10);
109+
$sheet->getCell('A1')->setValue(1);
97110
$sheet->getCell('B1')->setValue('Hello');
98111
$sheet->getCell('C1')->setValue(true);
99112
$sheet->getCell('D1')->setValue('=IF(1>2, TRUE, FALSE)');
113+
$sheet->getCell('E1')->setValueExplicit(1, DataType::TYPE_STRING);
114+
$sheet->getCell('F1')->setValue('="A"&"B"');
115+
$sheet->getCell('G1')->setValue('=1+2');
100116
$calc = Calculation::getInstance();
101117
$calc->setLocale('fr');
102118
$writer = new HtmlWriter($spreadsheet);
103119
$writer->setBetterBoolean(true);
104120
$html = $writer->generateHtmlAll();
105-
self::assertStringContainsString('VRAI', $html);
106121
self::assertStringNotContainsString('TRUE', $html);
122+
self::assertStringContainsString('<td data-type="b" class="column2 style0 b">VRAI</td>', $html);
123+
self::assertStringContainsString('<td data-type="b" class="column3 style0 b">FAUX</td>', $html);
124+
self::assertStringContainsString('<td data-type="s" class="column4 style0 s">1</td>', $html);
125+
self::assertStringContainsString('<td class="column5 style0 s">AB</td>', $html);
126+
self::assertStringContainsString('<td class="column6 style0 n">3</td>', $html);
107127

108128
/** @var callable */
109129
$callableWriter = [$this, 'setBetter'];
110130
$reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
111131
$spreadsheet->disconnectWorksheets();
112132

113133
$rsheet = $reloaded->getActiveSheet();
114-
self::assertSame(10, $rsheet->getCell('A1')->getValue());
134+
self::assertSame(1, $rsheet->getCell('A1')->getValue());
115135
self::assertSame('Hello', $rsheet->getCell('B1')->getValue());
116136
self::assertTrue($rsheet->getCell('C1')->getValue());
117137
self::assertFalse($rsheet->getCell('D1')->getValue());
138+
self::assertSame('1', $rsheet->getCell('E1')->getValue());
139+
self::assertSame('AB', $rsheet->getCell('F1')->getValue());
140+
self::assertSame(3, $rsheet->getCell('G1')->getValue());
118141
$reloaded->disconnectWorksheets();
119142
}
120143

121144
public function testForeignNoLocale(): void
122145
{
123146
$fragment = '<table><tbody><tr>'
124-
. '<td>10</td>'
147+
. '<td>1</td>'
125148
. '<td>Hello</td>'
126149
. '<td data-type="b">ИСТИНА</td>' // Bulgarian TRUE
127150
. '<td data-type="b">EPÄTOSI</td>' // Finnish FALSE
128151
. '<td data-type="b">whatever</td>'
129152
. '<td data-type="b">tRuE</td>'
153+
. '<td data-type="s">1</td>'
130154
. '</tr></tbody></table>';
131155
$reader = new HtmlReader();
132156
$spreadsheet = $reader->loadFromString($fragment);
133157
$sheet = $spreadsheet->getActiveSheet();
158+
self::assertSame(1, $sheet->getCell('A1')->getValue());
159+
self::assertSame('Hello', $sheet->getCell('B1')->getValue());
134160
self::assertTrue($sheet->getCell('C1')->getValue());
135161
self::assertFalse($sheet->getCell('D1')->getValue());
136162
self::assertSame('whatever', $sheet->getCell('E1')->getValue());
137163
self::assertTrue($sheet->getCell('F1')->getValue());
164+
self::assertSame('1', $sheet->getCell('G1')->getValue());
138165
$spreadsheet->disconnectWorksheets();
139166
}
140167
}

0 commit comments

Comments
 (0)