Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Html Reader/Writer Better Handling of Booleans #4257

Merged
merged 5 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org).

### Fixed

- Html Reader/Writer Better Handling of Booleans. [PR #4257](https://github.com/PHPOffice/PhpSpreadsheet/pull/4257)
- 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)
- Remove Unneccesary files from Composer Package. [PR #4262](https://github.com/PHPOffice/PhpSpreadsheet/pull/4262)
- 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)
- Fix minor break handling drawings. [Issue #4241](https://github.com/PHPOffice/PhpSpreadsheet/issues/4241) [PR #4244](https://github.com/PHPOffice/PhpSpreadsheet/pull/4244)
- 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)
Expand Down
47 changes: 47 additions & 0 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -3141,6 +3141,53 @@ private function getLocaleFile(string $localeDir, string $locale, string $langua
return $localeFileName;
}

/** @var array<int, array<int, string>> */
private static array $falseTrueArray = [];

/** @return array<int, array<int, string>> */
public function getFalseTrueArray(): array
{
if (!empty(self::$falseTrueArray)) {
return self::$falseTrueArray;
}
if (count(self::$validLocaleLanguages) == 1) {
self::loadLocales();
}
$falseTrueArray = [['FALSE'], ['TRUE']];
foreach (self::$validLocaleLanguages as $language) {
if (str_starts_with($language, 'en')) {
continue;
}
$locale = $language;
if (str_contains($locale, '_')) {
[$language] = explode('_', $locale);
}
$localeDir = implode(DIRECTORY_SEPARATOR, [__DIR__, 'locale', null]);

try {
$functionNamesFile = $this->getLocaleFile($localeDir, $locale, $language, 'functions');
} catch (Exception $e) {
continue;
}
// Retrieve the list of locale or language specific function names
$localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
foreach ($localeFunctions as $localeFunction) {
[$localeFunction] = explode('##', $localeFunction); // Strip out comments
if (str_contains($localeFunction, '=')) {
[$fName, $lfName] = array_map('trim', explode('=', $localeFunction));
if ($fName === 'FALSE') {
$falseTrueArray[0][] = $lfName;
} elseif ($fName === 'TRUE') {
$falseTrueArray[1][] = $lfName;
}
}
}
}
self::$falseTrueArray = $falseTrueArray;

return $falseTrueArray;
}

/**
* Set the locale code.
*
Expand Down
32 changes: 32 additions & 0 deletions src/PhpSpreadsheet/Reader/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use DOMElement;
use DOMNode;
use DOMText;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Comment;
Expand Down Expand Up @@ -271,6 +272,12 @@ protected function flushCell(Worksheet $sheet, string $column, int|string $row,
->setQuotePrefix(true);
}
}
if ($datatype === DataType::TYPE_BOOL) {
$cellContent = self::convertBoolean($cellContent);
if (!is_bool($cellContent)) {
$attributeArray['data-type'] = DataType::TYPE_STRING;
}
}

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

/** @var array<int, array<int, string>> */
private static array $falseTrueArray = [];

private static function convertBoolean(?string $cellContent): bool|string
{
if ($cellContent === '1') {
return true;
}
if ($cellContent === '0' || $cellContent === '' || $cellContent === null) {
return false;
}
if (empty(self::$falseTrueArray)) {
$calc = Calculation::getInstance();
self::$falseTrueArray = $calc->getFalseTrueArray();
}
if (in_array(mb_strtoupper($cellContent), self::$falseTrueArray[1], true)) {
return true;
}
if (in_array(mb_strtoupper($cellContent), self::$falseTrueArray[0], true)) {
return false;
}

return $cellContent;
}

private function processDomElementBody(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child): void
{
$attributeArray = [];
Expand Down
64 changes: 60 additions & 4 deletions src/PhpSpreadsheet/Writer/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Comment;
use PhpOffice\PhpSpreadsheet\Document\Properties;
Expand Down Expand Up @@ -141,13 +142,22 @@ class Html extends BaseWriter
/** @var Chart[] */
private $sheetCharts;

private bool $betterBoolean = false;

private string $getTrue = 'TRUE';

private string $getFalse = 'FALSE';

/**
* Create a new HTML.
*/
public function __construct(Spreadsheet $spreadsheet)
{
$this->spreadsheet = $spreadsheet;
$this->defaultFont = $this->spreadsheet->getDefaultStyle()->getFont();
$calc = Calculation::getInstance($this->spreadsheet);
$this->getTrue = $calc->getTRUE();
$this->getFalse = $calc->getFALSE();
}

/**
Expand Down Expand Up @@ -1353,8 +1363,21 @@ private function generateRowCellDataValue(Worksheet $worksheet, Cell $cell, stri
if ($cell->getValue() instanceof RichText) {
$cellData .= $this->generateRowCellDataValueRich($cell->getValue());
} else {
$origData = $this->preCalculateFormulas ? $cell->getCalculatedValue() : $cell->getValue();
$origData2 = $this->preCalculateFormulas ? $cell->getCalculatedValueString() : $cell->getValueString();
if ($this->preCalculateFormulas) {
$origData = $cell->getCalculatedValue();
if ($this->betterBoolean && is_bool($origData)) {
$origData2 = $origData ? $this->getTrue : $this->getFalse;
} else {
$origData2 = $cell->getCalculatedValueString();
}
} else {
$origData = $cell->getValue();
if ($this->betterBoolean && is_bool($origData)) {
$origData2 = $origData ? $this->getTrue : $this->getFalse;
} else {
$origData2 = $cell->getValueString();
}
}
$formatCode = $worksheet->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode();

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

// Extend CSS class?
$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;
}
}
if (!$this->useInlineCss && is_string($cssClass)) {
$cssClass .= ' style' . $cell->getXfIndex();
$cssClass .= ' ' . $cell->getDataType();
$cssClass .= ' ' . $dataType;
} elseif (is_array($cssClass)) {
$index = $cell->getXfIndex();
$styleIndex = 'td.style' . $index . ', th.style' . $index;
Expand All @@ -1410,7 +1444,7 @@ private function generateRowCellData(Worksheet $worksheet, null|Cell|string $cel
$sharedStyle->getAlignment()->getHorizontal() == Alignment::HORIZONTAL_GENERAL
&& isset($this->cssStyles['.' . $cell->getDataType()]['text-align'])
) {
$cssClass['text-align'] = $this->cssStyles['.' . $cell->getDataType()]['text-align'];
$cssClass['text-align'] = $this->cssStyles['.' . $dataType]['text-align'];
}
}
} else {
Expand Down Expand Up @@ -1455,6 +1489,16 @@ private function generateRowWriteCell(
$htmlx .= $this->generateRowIncludeCharts($worksheet, $coordinate);
// Column start
$html .= ' <' . $cellType;
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 . '"';
if ($htmlx) {
Expand Down Expand Up @@ -1910,4 +1954,16 @@ private function shouldGenerateColumn(Worksheet $sheet, string $colStr): bool

return $sheet->getColumnDimension($colStr)->getVisible();
}

public function getBetterBoolean(): bool
{
return $this->betterBoolean;
}

public function setBetterBoolean(bool $betterBoolean): self
{
$this->betterBoolean = $betterBoolean;

return $this;
}
}
Loading
Loading