Skip to content

Commit e23c987

Browse files
authored
Merge pull request #4257 from oleibman/htmlbool
Html Reader/Writer Better Handling of Booleans
2 parents 9dc82e6 + 40d0b8e commit e23c987

File tree

5 files changed

+353
-4
lines changed

5 files changed

+353
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org).
2525

2626
### Fixed
2727

28+
- Html Reader/Writer Better Handling of Booleans. [PR #4257](https://github.com/PHPOffice/PhpSpreadsheet/pull/4257)
29+
- Fill Patterns/Colors When Xml Attributes are Missing. [Issue #4248](https://github.com/PHPOffice/PhpSpreadsheet/issues/4248) [PR #4250](https://github.com/PHPOffice/PhpSpreadsheet/pull/4250)
30+
- Remove Unneccesary files from Composer Package. [PR #4262](https://github.com/PHPOffice/PhpSpreadsheet/pull/4262)
2831
- Swapped row and column indexes in ReferenceHelper. [Issue #4246](https://github.com/PHPOffice/PhpSpreadsheet/issues/4246) [PR #4247](https://github.com/PHPOffice/PhpSpreadsheet/pull/4247)
2932
- Fix minor break handling drawings. [Issue #4241](https://github.com/PHPOffice/PhpSpreadsheet/issues/4241) [PR #4244](https://github.com/PHPOffice/PhpSpreadsheet/pull/4244)
3033
- Ignore cell formatting when the format is a single @. [Issue #4242](https://github.com/PHPOffice/PhpSpreadsheet/issues/4242) [PR #4243](https://github.com/PHPOffice/PhpSpreadsheet/pull/4243)

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3141,6 +3141,53 @@ private function getLocaleFile(string $localeDir, string $locale, string $langua
31413141
return $localeFileName;
31423142
}
31433143

3144+
/** @var array<int, array<int, string>> */
3145+
private static array $falseTrueArray = [];
3146+
3147+
/** @return array<int, array<int, string>> */
3148+
public function getFalseTrueArray(): array
3149+
{
3150+
if (!empty(self::$falseTrueArray)) {
3151+
return self::$falseTrueArray;
3152+
}
3153+
if (count(self::$validLocaleLanguages) == 1) {
3154+
self::loadLocales();
3155+
}
3156+
$falseTrueArray = [['FALSE'], ['TRUE']];
3157+
foreach (self::$validLocaleLanguages as $language) {
3158+
if (str_starts_with($language, 'en')) {
3159+
continue;
3160+
}
3161+
$locale = $language;
3162+
if (str_contains($locale, '_')) {
3163+
[$language] = explode('_', $locale);
3164+
}
3165+
$localeDir = implode(DIRECTORY_SEPARATOR, [__DIR__, 'locale', null]);
3166+
3167+
try {
3168+
$functionNamesFile = $this->getLocaleFile($localeDir, $locale, $language, 'functions');
3169+
} catch (Exception $e) {
3170+
continue;
3171+
}
3172+
// Retrieve the list of locale or language specific function names
3173+
$localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
3174+
foreach ($localeFunctions as $localeFunction) {
3175+
[$localeFunction] = explode('##', $localeFunction); // Strip out comments
3176+
if (str_contains($localeFunction, '=')) {
3177+
[$fName, $lfName] = array_map('trim', explode('=', $localeFunction));
3178+
if ($fName === 'FALSE') {
3179+
$falseTrueArray[0][] = $lfName;
3180+
} elseif ($fName === 'TRUE') {
3181+
$falseTrueArray[1][] = $lfName;
3182+
}
3183+
}
3184+
}
3185+
}
3186+
self::$falseTrueArray = $falseTrueArray;
3187+
3188+
return $falseTrueArray;
3189+
}
3190+
31443191
/**
31453192
* Set the locale code.
31463193
*

src/PhpSpreadsheet/Reader/Html.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use DOMElement;
88
use DOMNode;
99
use DOMText;
10+
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
1011
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
1112
use PhpOffice\PhpSpreadsheet\Cell\DataType;
1213
use PhpOffice\PhpSpreadsheet\Comment;
@@ -271,6 +272,12 @@ protected function flushCell(Worksheet $sheet, string $column, int|string $row,
271272
->setQuotePrefix(true);
272273
}
273274
}
275+
if ($datatype === DataType::TYPE_BOOL) {
276+
$cellContent = self::convertBoolean($cellContent);
277+
if (!is_bool($cellContent)) {
278+
$attributeArray['data-type'] = DataType::TYPE_STRING;
279+
}
280+
}
274281

275282
//catching the Exception and ignoring the invalid data types
276283
try {
@@ -291,6 +298,31 @@ protected function flushCell(Worksheet $sheet, string $column, int|string $row,
291298
$cellContent = (string) '';
292299
}
293300

301+
/** @var array<int, array<int, string>> */
302+
private static array $falseTrueArray = [];
303+
304+
private static function convertBoolean(?string $cellContent): bool|string
305+
{
306+
if ($cellContent === '1') {
307+
return true;
308+
}
309+
if ($cellContent === '0' || $cellContent === '' || $cellContent === null) {
310+
return false;
311+
}
312+
if (empty(self::$falseTrueArray)) {
313+
$calc = Calculation::getInstance();
314+
self::$falseTrueArray = $calc->getFalseTrueArray();
315+
}
316+
if (in_array(mb_strtoupper($cellContent), self::$falseTrueArray[1], true)) {
317+
return true;
318+
}
319+
if (in_array(mb_strtoupper($cellContent), self::$falseTrueArray[0], true)) {
320+
return false;
321+
}
322+
323+
return $cellContent;
324+
}
325+
294326
private function processDomElementBody(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child): void
295327
{
296328
$attributeArray = [];

src/PhpSpreadsheet/Writer/Html.php

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
66
use PhpOffice\PhpSpreadsheet\Cell\Cell;
77
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
8+
use PhpOffice\PhpSpreadsheet\Cell\DataType;
89
use PhpOffice\PhpSpreadsheet\Chart\Chart;
910
use PhpOffice\PhpSpreadsheet\Comment;
1011
use PhpOffice\PhpSpreadsheet\Document\Properties;
@@ -141,13 +142,22 @@ class Html extends BaseWriter
141142
/** @var Chart[] */
142143
private $sheetCharts;
143144

145+
private bool $betterBoolean = false;
146+
147+
private string $getTrue = 'TRUE';
148+
149+
private string $getFalse = 'FALSE';
150+
144151
/**
145152
* Create a new HTML.
146153
*/
147154
public function __construct(Spreadsheet $spreadsheet)
148155
{
149156
$this->spreadsheet = $spreadsheet;
150157
$this->defaultFont = $this->spreadsheet->getDefaultStyle()->getFont();
158+
$calc = Calculation::getInstance($this->spreadsheet);
159+
$this->getTrue = $calc->getTRUE();
160+
$this->getFalse = $calc->getFALSE();
151161
}
152162

153163
/**
@@ -1353,8 +1363,21 @@ private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, stri
13531363
if ($cell->getValue() instanceof RichText) {
13541364
$cellData .= $this->generateRowCellDataValueRich($cell->getValue());
13551365
} else {
1356-
$origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue();
1357-
$origData2 = $this->preCalculateFormulas ? $cell->getCalculatedValueString() : $cell->getValueString();
1366+
if ($this->preCalculateFormulas) {
1367+
$origData = $cell->getCalculatedValue();
1368+
if ($this->betterBoolean && is_bool($origData)) {
1369+
$origData2 = $origData ? $this->getTrue : $this->getFalse;
1370+
} else {
1371+
$origData2 = $cell->getCalculatedValueString();
1372+
}
1373+
} else {
1374+
$origData = $cell->getValue();
1375+
if ($this->betterBoolean && is_bool($origData)) {
1376+
$origData2 = $origData ? $this->getTrue : $this->getFalse;
1377+
} else {
1378+
$origData2 = $cell->getValueString();
1379+
}
1380+
}
13581381
$formatCode = $worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode();
13591382

13601383
$cellData = NumberFormat::toFormattedString(
@@ -1394,9 +1417,20 @@ private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cel
13941417
$cellData = nl2br($cellData);
13951418

13961419
// Extend CSS class?
1420+
$dataType = $cell->getDataType();
1421+
if ($this->betterBoolean && $this->preCalculateFormulas && $dataType === DataType::TYPE_FORMULA) {
1422+
$calculatedValue = $cell->getCalculatedValue();
1423+
if (is_bool($calculatedValue)) {
1424+
$dataType = DataType::TYPE_BOOL;
1425+
} elseif (is_numeric($calculatedValue)) {
1426+
$dataType = DataType::TYPE_NUMERIC;
1427+
} elseif (is_string($calculatedValue)) {
1428+
$dataType = DataType::TYPE_STRING;
1429+
}
1430+
}
13971431
if (!$this->useInlineCss && is_string($cssClass)) {
13981432
$cssClass .= ' style' . $cell->getXfIndex();
1399-
$cssClass .= ' ' . $cell->getDataType();
1433+
$cssClass .= ' ' . $dataType;
14001434
} elseif (is_array($cssClass)) {
14011435
$index = $cell->getXfIndex();
14021436
$styleIndex = 'td.style' . $index . ', th.style' . $index;
@@ -1410,7 +1444,7 @@ private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cel
14101444
$sharedStyle->getAlignment()->getHorizontal() == Alignment::HORIZONTAL_GENERAL
14111445
&& isset($this->cssStyles['.' . $cell->getDataType()]['text-align'])
14121446
) {
1413-
$cssClass['text-align'] = $this->cssStyles['.' . $cell->getDataType()]['text-align'];
1447+
$cssClass['text-align'] = $this->cssStyles['.' . $dataType]['text-align'];
14141448
}
14151449
}
14161450
} else {
@@ -1455,6 +1489,16 @@ private function generateRowWriteCell(
14551489
$htmlx .= $this->generateRowIncludeCharts($worksheet, $coordinate);
14561490
// Column start
14571491
$html .= ' <' . $cellType;
1492+
if ($this->betterBoolean) {
1493+
$dataType = $worksheet->getCell($coordinate)->getDataType();
1494+
if ($dataType === DataType::TYPE_BOOL) {
1495+
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
1496+
} elseif ($dataType === DataType::TYPE_FORMULA && is_bool($worksheet->getCell($coordinate)->getCalculatedValue())) {
1497+
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
1498+
} elseif (is_numeric($cellData) && $worksheet->getCell($coordinate)->getDataType() === DataType::TYPE_STRING) {
1499+
$html .= ' data-type="' . DataType::TYPE_STRING . '"';
1500+
}
1501+
}
14581502
if (!$this->useInlineCss && !$this->isPdf && is_string($cssClass)) {
14591503
$html .= ' class="' . $cssClass . '"';
14601504
if ($htmlx) {
@@ -1910,4 +1954,16 @@ private function shouldGenerateColumn(Worksheet $sheet, string $colStr): bool
19101954

19111955
return $sheet->getColumnDimension($colStr)->getVisible();
19121956
}
1957+
1958+
public function getBetterBoolean(): bool
1959+
{
1960+
return $this->betterBoolean;
1961+
}
1962+
1963+
public function setBetterBoolean(bool $betterBoolean): self
1964+
{
1965+
$this->betterBoolean = $betterBoolean;
1966+
1967+
return $this;
1968+
}
19131969
}

0 commit comments

Comments
 (0)